summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/media/v4l/controls.xml11
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml99
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb12.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt.xml1
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml8
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/nokia,smia.txt63
-rw-r--r--Documentation/devicetree/bindings/media/sunxi-ir.txt4
-rw-r--r--Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt61
-rw-r--r--Documentation/devicetree/bindings/media/video-interfaces.txt3
-rw-r--r--Documentation/video4linux/CQcam.txt205
-rw-r--r--Documentation/video4linux/README.tlg230047
-rw-r--r--Documentation/video4linux/v4l2-framework.txt25
-rw-r--r--Documentation/video4linux/w9966.txt33
-rw-r--r--MAINTAINERS41
-rw-r--r--drivers/media/common/Kconfig4
-rw-r--r--drivers/media/common/Makefile1
-rw-r--r--drivers/media/common/btcx-risc.h6
-rw-r--r--drivers/media/dvb-core/dvb_net.c88
-rw-r--r--drivers/media/dvb-frontends/Kconfig4
-rw-r--r--drivers/media/dvb-frontends/au8522.h5
-rw-r--r--drivers/media/dvb-frontends/dib8000.c3
-rw-r--r--drivers/media/dvb-frontends/hd29l2.c10
-rw-r--r--drivers/media/dvb-frontends/lg2160.c6
-rw-r--r--drivers/media/dvb-frontends/lgdt3305.c23
-rw-r--r--drivers/media/dvb-frontends/lgdt3305.h6
-rw-r--r--drivers/media/dvb-frontends/lgdt330x.c6
-rw-r--r--drivers/media/dvb-frontends/lgdt330x.h6
-rw-r--r--drivers/media/dvb-frontends/lgdt330x_priv.h6
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.c4
-rw-r--r--drivers/media/dvb-frontends/mn88472.h6
-rw-r--r--drivers/media/dvb-frontends/nxt200x.h6
-rw-r--r--drivers/media/dvb-frontends/or51132.c6
-rw-r--r--drivers/media/dvb-frontends/or51132.h6
-rw-r--r--drivers/media/dvb-frontends/rtl2830.c944
-rw-r--r--drivers/media/dvb-frontends/rtl2830.h79
-rw-r--r--drivers/media/dvb-frontends/rtl2830_priv.h24
-rw-r--r--drivers/media/dvb-frontends/rtl2832.c1336
-rw-r--r--drivers/media/dvb-frontends/rtl2832.h99
-rw-r--r--drivers/media/dvb-frontends/rtl2832_priv.h32
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c1189
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.h57
-rw-r--r--drivers/media/dvb-frontends/s5h1409.c6
-rw-r--r--drivers/media/dvb-frontends/s5h1409.h5
-rw-r--r--drivers/media/dvb-frontends/s5h1411.c5
-rw-r--r--drivers/media/dvb-frontends/s5h1411.h5
-rw-r--r--drivers/media/dvb-frontends/si2168.c317
-rw-r--r--drivers/media/dvb-frontends/si2168.h6
-rw-r--r--drivers/media/dvb-frontends/si2168_priv.h3
-rw-r--r--drivers/media/dvb-frontends/stb0899_algo.c5
-rw-r--r--drivers/media/dvb-frontends/stb0899_drv.c7
-rw-r--r--drivers/media/dvb-frontends/tc90522.c1
-rw-r--r--drivers/media/i2c/Kconfig9
-rw-r--r--drivers/media/i2c/adv7180.c1010
-rw-r--r--drivers/media/i2c/adv7604.c76
-rw-r--r--drivers/media/i2c/adv7842.c184
-rw-r--r--drivers/media/i2c/m5mols/m5mols_core.c9
-rw-r--r--drivers/media/i2c/msp3400-driver.c8
-rw-r--r--drivers/media/i2c/mt9m032.c42
-rw-r--r--drivers/media/i2c/mt9p031.c41
-rw-r--r--drivers/media/i2c/mt9t001.c41
-rw-r--r--drivers/media/i2c/mt9v032.c43
-rw-r--r--drivers/media/i2c/s5k4ecgx.c11
-rw-r--r--drivers/media/i2c/s5k5baf.c13
-rw-r--r--drivers/media/i2c/s5k6aa.c46
-rw-r--r--drivers/media/i2c/smiapp-pll.c7
-rw-r--r--drivers/media/i2c/smiapp-pll.h8
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c386
-rw-r--r--drivers/media/i2c/smiapp/smiapp-limits.c6
-rw-r--r--drivers/media/i2c/smiapp/smiapp-limits.h6
-rw-r--r--drivers/media/i2c/smiapp/smiapp-quirk.c14
-rw-r--r--drivers/media/i2c/smiapp/smiapp-quirk.h24
-rw-r--r--drivers/media/i2c/smiapp/smiapp-reg-defs.h6
-rw-r--r--drivers/media/i2c/smiapp/smiapp-reg.h6
-rw-r--r--drivers/media/i2c/smiapp/smiapp-regs.c6
-rw-r--r--drivers/media/i2c/smiapp/smiapp-regs.h6
-rw-r--r--drivers/media/i2c/smiapp/smiapp.h7
-rw-r--r--drivers/media/i2c/soc_camera/ov2640.c82
-rw-r--r--drivers/media/i2c/ths8200.c10
-rw-r--r--drivers/media/mmc/siano/Kconfig2
-rw-r--r--drivers/media/pci/bt8xx/Kconfig4
-rw-r--r--drivers/media/pci/bt8xx/Makefile2
-rw-r--r--drivers/media/pci/bt8xx/bt878.c6
-rw-r--r--drivers/media/pci/bt8xx/btcx-risc.c (renamed from drivers/media/common/btcx-risc.c)36
-rw-r--r--drivers/media/pci/bt8xx/btcx-risc.h26
-rw-r--r--drivers/media/pci/bt8xx/bttv-cards.c324
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c44
-rw-r--r--drivers/media/pci/bt8xx/bttv-gpio.c6
-rw-r--r--drivers/media/pci/bt8xx/bttv-if.c6
-rw-r--r--drivers/media/pci/bt8xx/bttv-risc.c6
-rw-r--r--drivers/media/pci/bt8xx/bttv-vbi.c7
-rw-r--r--drivers/media/pci/bt8xx/bttv.h5
-rw-r--r--drivers/media/pci/bt8xx/bttvp.h20
-rw-r--r--drivers/media/pci/cx23885/Kconfig1
-rw-r--r--drivers/media/pci/cx23885/cx23885-cards.c43
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c376
-rw-r--r--drivers/media/pci/cx23885/cx23885-i2c.c4
-rw-r--r--drivers/media/pci/cx23885/cx23885.h3
-rw-r--r--drivers/media/pci/cx25821/Kconfig3
-rw-r--r--drivers/media/pci/cx25821/Makefile3
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c113
-rw-r--r--drivers/media/pci/cx25821/cx25821-core.c112
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c685
-rw-r--r--drivers/media/pci/cx25821/cx25821.h48
-rw-r--r--drivers/media/pci/cx88/cx88-blackbird.c3
-rw-r--r--drivers/media/pci/cx88/cx88-core.c7
-rw-r--r--drivers/media/pci/cx88/cx88-dvb.c4
-rw-r--r--drivers/media/pci/cx88/cx88-mpeg.c7
-rw-r--r--drivers/media/pci/cx88/cx88-tvaudio.c7
-rw-r--r--drivers/media/pci/ivtv/ivtv-irq.c22
-rw-r--r--drivers/media/pci/mantis/mantis_core.c23
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c5
-rw-r--r--drivers/media/pci/smipcie/smipcie.c12
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-core.c4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-eeprom.c2
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-enc.c6
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-g723.c4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-jpeg.h4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-tw28.c4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c48
-rw-r--r--drivers/media/pci/solo6x10/solo6x10.h6
-rw-r--r--drivers/media/pci/sta2x11/Kconfig1
-rw-r--r--drivers/media/pci/ttpci/av7110.c5
-rw-r--r--drivers/media/pci/ttpci/budget-core.c89
-rw-r--r--drivers/media/pci/tw68/tw68.h1
-rw-r--r--drivers/media/platform/Kconfig11
-rw-r--r--drivers/media/platform/Makefile2
-rw-r--r--drivers/media/platform/am437x/Kconfig11
-rw-r--r--drivers/media/platform/am437x/Makefile3
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.c2776
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.h283
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe_regs.h140
-rw-r--r--drivers/media/platform/coda/coda-bit.c25
-rw-r--r--drivers/media/platform/coda/coda-common.c165
-rw-r--r--drivers/media/platform/coda/coda.h2
-rw-r--r--drivers/media/platform/coda/coda_regs.h4
-rw-r--r--drivers/media/platform/davinci/Kconfig6
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.h12
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-m2m.c6
-rw-r--r--drivers/media/platform/marvell-ccic/Kconfig3
-rw-r--r--drivers/media/platform/marvell-ccic/mcam-core.c1
-rw-r--r--drivers/media/platform/omap3isp/isp.c3
-rw-r--r--drivers/media/platform/s3c-camif/camif-capture.c17
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.c1
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c1
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c23
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_enc.c21
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c6
-rw-r--r--drivers/media/platform/s5p-tv/mixer_video.c21
-rw-r--r--drivers/media/platform/sh_veu.c35
-rw-r--r--drivers/media/platform/soc_camera/atmel-isi.c7
-rw-r--r--drivers/media/platform/soc_camera/mx3_camera.c7
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c94
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c7
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c18
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c162
-rw-r--r--drivers/media/platform/vivid/vivid-ctrls.c4
-rw-r--r--drivers/media/platform/vivid/vivid-tpg.c10
-rw-r--r--drivers/media/platform/vivid/vivid-tpg.h1
-rw-r--r--drivers/media/platform/vsp1/vsp1.h14
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.c2
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c81
-rw-r--r--drivers/media/platform/vsp1/vsp1_hsit.c5
-rw-r--r--drivers/media/platform/vsp1/vsp1_regs.h4
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c18
-rw-r--r--drivers/media/platform/vsp1/vsp1_rwpf.h1
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c13
-rw-r--r--drivers/media/radio/radio-aimslab.c4
-rw-r--r--drivers/media/radio/tea575x.c41
-rw-r--r--drivers/media/radio/wl128x/fmdrv_rx.c16
-rw-r--r--drivers/media/radio/wl128x/fmdrv_rx.h1
-rw-r--r--drivers/media/rc/img-ir/Kconfig15
-rw-r--r--drivers/media/rc/img-ir/Makefile2
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.c84
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.h24
-rw-r--r--drivers/media/rc/img-ir/img-ir-jvc.c8
-rw-r--r--drivers/media/rc/img-ir/img-ir-nec.c24
-rw-r--r--drivers/media/rc/img-ir/img-ir-rc5.c88
-rw-r--r--drivers/media/rc/img-ir/img-ir-rc6.c117
-rw-r--r--drivers/media/rc/img-ir/img-ir-sanyo.c8
-rw-r--r--drivers/media/rc/img-ir/img-ir-sharp.c8
-rw-r--r--drivers/media/rc/img-ir/img-ir-sony.c12
-rw-r--r--drivers/media/rc/lirc_dev.c6
-rw-r--r--drivers/media/rc/rc-main.c14
-rw-r--r--drivers/media/rc/sunxi-cir.c46
-rw-r--r--drivers/media/tuners/mt20xx.c8
-rw-r--r--drivers/media/tuners/mt2131.c5
-rw-r--r--drivers/media/tuners/mt2131.h5
-rw-r--r--drivers/media/tuners/mt2131_priv.h5
-rw-r--r--drivers/media/tuners/mxl5007t.c8
-rw-r--r--drivers/media/tuners/mxl5007t.h9
-rw-r--r--drivers/media/tuners/si2157.c189
-rw-r--r--drivers/media/tuners/si2157_priv.h3
-rw-r--r--drivers/media/tuners/tda18271-fe.c8
-rw-r--r--drivers/media/tuners/tda18271-maps.c8
-rw-r--r--drivers/media/tuners/tda18271-priv.h8
-rw-r--r--drivers/media/tuners/tda827x.c8
-rw-r--r--drivers/media/tuners/tda8290.c8
-rw-r--r--drivers/media/tuners/tda9887.c8
-rw-r--r--drivers/media/tuners/tuner-simple.c8
-rw-r--r--drivers/media/usb/au0828/Kconfig2
-rw-r--r--drivers/media/usb/au0828/au0828-cards.c2
-rw-r--r--drivers/media/usb/au0828/au0828-vbi.c122
-rw-r--r--drivers/media/usb/au0828/au0828-video.c976
-rw-r--r--drivers/media/usb/au0828/au0828.h61
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-cards.c9
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-video.c1
-rw-r--r--drivers/media/usb/cx231xx/cx231xx.h10
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb.h2
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c1
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.c336
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c8
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h9
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c6
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.h6
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.c940
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.h27
-rw-r--r--drivers/media/usb/dvb-usb/m920x.c5
-rw-r--r--drivers/media/usb/em28xx/em28xx-audio.c8
-rw-r--r--drivers/media/usb/em28xx/em28xx-core.c4
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c14
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c9
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c7
-rw-r--r--drivers/media/usb/gspca/Kconfig10
-rw-r--r--drivers/media/usb/gspca/Makefile2
-rw-r--r--drivers/media/usb/gspca/gspca.c2
-rw-r--r--drivers/media/usb/gspca/ov534.c10
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx.c4
-rw-r--r--drivers/media/usb/gspca/touptek.c731
-rw-r--r--drivers/media/usb/gspca/vc032x.c10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-audio.c10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-audio.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-context.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-context.h9
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-ctrl.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-ctrl.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c12
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-debug.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-debugifc.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-debugifc.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-devattr.c10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-devattr.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-eeprom.c10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-eeprom.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-encoder.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-encoder.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-hdw.c50
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-hdw.h13
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-io.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-io.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-ioread.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-ioread.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-main.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-std.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-std.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-sysfs.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-sysfs.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-util.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-v4l2.c10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-v4l2.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c11
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-wm8775.c12
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-wm8775.h10
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2.h10
-rw-r--r--drivers/media/usb/pwc/pwc-if.c12
-rw-r--r--drivers/media/usb/s2255/s2255drv.c4
-rw-r--r--drivers/media/usb/siano/Kconfig2
-rw-r--r--drivers/media/usb/stk1160/stk1160-v4l.c5
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c1
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c3
-rw-r--r--drivers/media/usb/usbvision/usbvision-core.c13
-rw-r--r--drivers/media/usb/usbvision/usbvision-i2c.c8
-rw-r--r--drivers/media/usb/usbvision/usbvision-video.c8
-rw-r--r--drivers/media/usb/usbvision/usbvision.h8
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c5
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c19
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c1
-rw-r--r--drivers/media/usb/uvc/uvc_video.c6
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h3
-rw-r--r--drivers/media/usb/zr364xx/zr364xx.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c35
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c10
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c8
-rw-r--r--drivers/media/v4l2-core/videobuf-dma-sg.c15
-rw-r--r--drivers/media/v4l2-core/videobuf2-vmalloc.c9
-rw-r--r--drivers/staging/media/Kconfig6
-rw-r--r--drivers/staging/media/Makefile4
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c6
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_isif.c69
-rw-r--r--drivers/staging/media/lirc/lirc_serial.c10
-rw-r--r--drivers/staging/media/lirc/lirc_zilog.c118
-rw-r--r--drivers/staging/media/mn88472/mn88472.c63
-rw-r--r--drivers/staging/media/mn88472/mn88472_priv.h1
-rw-r--r--drivers/staging/media/omap4iss/iss.c111
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c43
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.h2
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.c22
-rw-r--r--drivers/staging/media/omap4iss/iss_regs.h2
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.c18
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c16
-rw-r--r--drivers/staging/media/parport/Kconfig69
-rw-r--r--drivers/staging/media/parport/Makefile4
-rw-r--r--drivers/staging/media/parport/bw-qcam.c1177
-rw-r--r--drivers/staging/media/parport/c-qcam.c882
-rw-r--r--drivers/staging/media/parport/pms.c1156
-rw-r--r--drivers/staging/media/parport/w9966.c980
-rw-r--r--drivers/staging/media/tlg2300/Kconfig21
-rw-r--r--drivers/staging/media/tlg2300/Makefile9
-rw-r--r--drivers/staging/media/tlg2300/pd-alsa.c337
-rw-r--r--drivers/staging/media/tlg2300/pd-common.h271
-rw-r--r--drivers/staging/media/tlg2300/pd-dvb.c597
-rw-r--r--drivers/staging/media/tlg2300/pd-main.c553
-rw-r--r--drivers/staging/media/tlg2300/pd-radio.c339
-rw-r--r--drivers/staging/media/tlg2300/pd-video.c1570
-rw-r--r--drivers/staging/media/tlg2300/vendorcmds.h243
-rw-r--r--drivers/staging/media/vino/Kconfig24
-rw-r--r--drivers/staging/media/vino/Makefile3
-rw-r--r--drivers/staging/media/vino/indycam.c378
-rw-r--r--drivers/staging/media/vino/indycam.h93
-rw-r--r--drivers/staging/media/vino/saa7191.c649
-rw-r--r--drivers/staging/media/vino/saa7191.h245
-rw-r--r--drivers/staging/media/vino/vino.c4345
-rw-r--r--drivers/staging/media/vino/vino.h138
-rw-r--r--drivers/video/hdmi.c822
-rw-r--r--include/linux/hdmi.h37
-rw-r--r--include/linux/platform_data/vsp1.h27
-rw-r--r--include/media/smiapp.h10
-rw-r--r--include/media/tea575x.h5
-rw-r--r--include/media/v4l2-dev.h3
-rw-r--r--include/media/v4l2-ioctl.h15
-rw-r--r--include/media/v4l2-subdev.h6
-rw-r--r--include/media/videobuf-dma-sg.h8
-rw-r--r--include/media/videobuf-dvb.h6
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/am437x-vpfe.h122
-rw-r--r--include/uapi/linux/v4l2-controls.h4
-rw-r--r--include/uapi/linux/videodev2.h17
357 files changed, 12056 insertions, 21671 deletions
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index e013e4bf244c..4e9462f1ab4c 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2692,12 +2692,11 @@ in the S5P family of SoCs by Samsung.
 	      <row><entry></entry></row>
 	      <row>
 		<entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE</constant>&nbsp;</entry>
-		<entry>integer</entry>
-	      </row><row><entry spanname="descr">If the display delay is enabled then the decoder has to return a
-CAPTURE buffer after processing a certain number of OUTPUT buffers. If this number is low, then it may result in
-buffers not being dequeued in display order. In addition hardware may still use those buffers as reference, thus
-application should not write to those buffers. This feature can be used for example for generating thumbnails of videos.
-Applicable to the H264 decoder.
+		<entry>boolean</entry>
+	      </row><row><entry spanname="descr">If the display delay is enabled then the decoder is forced to return a
+CAPTURE buffer (decoded frame) after processing a certain number of OUTPUT buffers. The delay can be set through
+<constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY</constant>. This feature can be used for example
+for generating thumbnails of videos. Applicable to the H264 decoder.
 	      </entry>
 	      </row>
 	      <row><entry></entry></row>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml
index c1c62a9acc2a..f34d03ebda3a 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml
@@ -17,7 +17,7 @@
       <refsect1>
 	<title>Description</title>
 
-	<para>The following four pixel formats are raw sRGB / Bayer formats with
+	<para>These four pixel formats are raw sRGB / Bayer formats with
 10 bits per colour. Each colour component is stored in a 16-bit word, with 6
 unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
 and n/2 blue or red samples, with alternating red and blue rows. Bytes are
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml
index 29acc2098cc2..d2e5845e57fb 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml
@@ -25,7 +25,7 @@
 	  </refnamediv>
 	  <refsect1>
 	    <title>Description</title>
-	    <para>The following four pixel formats are raw sRGB / Bayer
+	    <para>These four pixel formats are raw sRGB / Bayer
 	    formats with 10 bits per color compressed to 8 bits each,
 	    using the A-LAW algorithm. Each color component consumes 8
 	    bits of memory. In other respects this format is similar to
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
index 2d3f0b1aefe0..bde89878c5c5 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
@@ -18,7 +18,7 @@
       <refsect1>
 	<title>Description</title>
 
-	<para>The following four pixel formats are raw sRGB / Bayer formats
+	<para>These four pixel formats are raw sRGB / Bayer formats
 	with 10 bits per colour compressed to 8 bits each, using DPCM
 	compression. DPCM, differential pulse-code modulation, is lossy.
 	Each colour component consumes 8 bits of memory. In other respects
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
new file mode 100644
index 000000000000..30aa63581fe3
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
@@ -0,0 +1,99 @@
+    <refentry id="pixfmt-srggb10p">
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_SRGGB10P ('pRAA'),
+	 V4L2_PIX_FMT_SGRBG10P ('pgAA'),
+	 V4L2_PIX_FMT_SGBRG10P ('pGAA'),
+	 V4L2_PIX_FMT_SBGGR10P ('pBAA'),
+	 </refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname id="V4L2-PIX-FMT-SRGGB10P"><constant>V4L2_PIX_FMT_SRGGB10P</constant></refname>
+	<refname id="V4L2-PIX-FMT-SGRBG10P"><constant>V4L2_PIX_FMT_SGRBG10P</constant></refname>
+	<refname id="V4L2-PIX-FMT-SGBRG10P"><constant>V4L2_PIX_FMT_SGBRG10P</constant></refname>
+	<refname id="V4L2-PIX-FMT-SBGGR10P"><constant>V4L2_PIX_FMT_SBGGR10P</constant></refname>
+	<refpurpose>10-bit packed Bayer formats</refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>These four pixel formats are packed raw sRGB /
+	Bayer formats with 10 bits per colour. Every four consecutive
+	colour components are packed into 5 bytes. Each of the first 4
+	bytes contain the 8 high order bits of the pixels, and the
+	fifth byte contains the two least significants bits of each
+	pixel, in the same order.</para>
+
+	<para>Each n-pixel row contains n/2 green samples and n/2 blue
+	or red samples, with alternating green-red and green-blue
+	rows. They are conventionally described as GRGR... BGBG...,
+	RGRG... GBGB..., etc. Below is an example of one of these
+	formats:</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_SBGGR10P</constant> 4 &times; 4
+      pixel image</title>
+
+      <formalpara>
+	<title>Byte Order.</title>
+	<para>Each cell is one byte.
+	  <informaltable frame="topbot" colsep="1" rowsep="1">
+	    <tgroup cols="5" align="center" border="1">
+	      <colspec align="left" colwidth="2*" />
+	      <tbody valign="top">
+		<row>
+		  <entry>start&nbsp;+&nbsp;0:</entry>
+		  <entry>B<subscript>00high</subscript></entry>
+		  <entry>G<subscript>01high</subscript></entry>
+		  <entry>B<subscript>02high</subscript></entry>
+		  <entry>G<subscript>03high</subscript></entry>
+		  <entry>B<subscript>00low</subscript>(bits 7--6)
+			 G<subscript>01low</subscript>(bits 5--4)
+			 B<subscript>02low</subscript>(bits 3--2)
+			 G<subscript>03low</subscript>(bits 1--0)
+		  </entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;5:</entry>
+		  <entry>G<subscript>10high</subscript></entry>
+		  <entry>R<subscript>11high</subscript></entry>
+		  <entry>G<subscript>12high</subscript></entry>
+		  <entry>R<subscript>13high</subscript></entry>
+		  <entry>G<subscript>10low</subscript>(bits 7--6)
+			 R<subscript>11low</subscript>(bits 5--4)
+			 G<subscript>12low</subscript>(bits 3--2)
+			 R<subscript>13low</subscript>(bits 1--0)
+		  </entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;10:</entry>
+		  <entry>B<subscript>20high</subscript></entry>
+		  <entry>G<subscript>21high</subscript></entry>
+		  <entry>B<subscript>22high</subscript></entry>
+		  <entry>G<subscript>23high</subscript></entry>
+		  <entry>B<subscript>20low</subscript>(bits 7--6)
+			 G<subscript>21low</subscript>(bits 5--4)
+			 B<subscript>22low</subscript>(bits 3--2)
+			 G<subscript>23low</subscript>(bits 1--0)
+		  </entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;15:</entry>
+		  <entry>G<subscript>30high</subscript></entry>
+		  <entry>R<subscript>31high</subscript></entry>
+		  <entry>G<subscript>32high</subscript></entry>
+		  <entry>R<subscript>33high</subscript></entry>
+		  <entry>G<subscript>30low</subscript>(bits 7--6)
+			 R<subscript>31low</subscript>(bits 5--4)
+			 G<subscript>32low</subscript>(bits 3--2)
+			 R<subscript>33low</subscript>(bits 1--0)
+		  </entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
index 96947f17fca1..0c8e4adf417f 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
@@ -17,7 +17,7 @@
       <refsect1>
 	<title>Description</title>
 
-	<para>The following four pixel formats are raw sRGB / Bayer formats with
+	<para>These four pixel formats are raw sRGB / Bayer formats with
 12 bits per colour. Each colour component is stored in a 16-bit word, with 4
 unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
 and n/2 blue or red samples, with alternating red and blue rows. Bytes are
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index d5eca4b8f74b..5e0352c50324 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -1405,6 +1405,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
     &sub-srggb8;
     &sub-sbggr16;
     &sub-srggb10;
+    &sub-srggb10p;
     &sub-srggb10alaw8;
     &sub-srggb10dpcm8;
     &sub-srggb12;
diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
index 28a8c1e1c705..a2017bfcaed2 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
@@ -212,11 +212,3 @@ standards set in the <structfield>standards</structfield> field.
     &return-value;
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
index b9fdfeacdbcb..6e3cadd4e1f9 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
@@ -131,11 +131,3 @@ is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
diff --git a/Documentation/devicetree/bindings/media/i2c/nokia,smia.txt b/Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
new file mode 100644
index 000000000000..855e1faf73e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
@@ -0,0 +1,63 @@
+SMIA/SMIA++ sensor
+
+SMIA (Standard Mobile Imaging Architecture) is an image sensor standard
+defined jointly by Nokia and ST. SMIA++, defined by Nokia, is an extension
+of that. These definitions are valid for both types of sensors.
+
+More detailed documentation can be found in
+Documentation/devicetree/bindings/media/video-interfaces.txt .
+
+
+Mandatory properties
+--------------------
+
+- compatible: "nokia,smia"
+- reg: I2C address (0x10, or an alternative address)
+- vana-supply: Analogue voltage supply (VANA), typically 2,8 volts (sensor
+  dependent).
+- clocks: External clock to the sensor
+- clock-frequency: Frequency of the external clock to the sensor
+- link-frequencies: List of allowed data link frequencies. An array of
+  64-bit elements.
+
+
+Optional properties
+-------------------
+
+- nokia,nvm-size: The size of the NVM, in bytes. If the size is not given,
+  the NVM contents will not be read.
+- reset-gpios: XSHUTDOWN GPIO
+
+
+Endpoint node mandatory properties
+----------------------------------
+
+- clock-lanes: <0>
+- data-lanes: <1..n>
+- remote-endpoint: A phandle to the bus receiver's endpoint node.
+
+
+Example
+-------
+
+&i2c2 {
+	clock-frequency = <400000>;
+
+	smiapp_1: camera@10 {
+		compatible = "nokia,smia";
+		reg = <0x10>;
+		reset-gpios = <&gpio3 20 0>;
+		vana-supply = <&vaux3>;
+		clocks = <&omap3_isp 0>;
+		clock-frequency = <9600000>;
+		nokia,nvm-size = <512>; /* 8 * 64 */
+		link-frequencies = /bits/ 64 <199200000 210000000 499200000>;
+		port {
+			smiapp_1_1: endpoint {
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+				remote-endpoint = <&csi2a_ep>;
+			};
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt
index 23dd5ad07b7c..1811a067c72c 100644
--- a/Documentation/devicetree/bindings/media/sunxi-ir.txt
+++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt
@@ -1,7 +1,7 @@
 Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
 
 Required properties:
-- compatible	    : should be "allwinner,sun4i-a10-ir";
+- compatible	    : "allwinner,sun4i-a10-ir" or "allwinner,sun5i-a13-ir"
 - clocks	    : list of clock specifiers, corresponding to
 		      entries in clock-names property;
 - clock-names	    : should contain "apb" and "ir" entries;
@@ -10,6 +10,7 @@ Required properties:
 
 Optional properties:
 - linux,rc-map-name : Remote control map name.
+- resets : phandle + reset specifier pair
 
 Example:
 
@@ -17,6 +18,7 @@ ir0: ir@01c21800 {
 	compatible = "allwinner,sun4i-a10-ir";
 	clocks = <&apb0_gates 6>, <&ir0_clk>;
 	clock-names = "apb", "ir";
+	resets = <&apb0_rst 1>;
 	interrupts = <0 5 1>;
 	reg = <0x01C21800 0x40>;
 	linux,rc-map-name = "rc-rc6-mce";
diff --git a/Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt b/Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt
new file mode 100644
index 000000000000..3932e766553a
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt
@@ -0,0 +1,61 @@
+Texas Instruments AM437x CAMERA (VPFE)
+--------------------------------------
+
+The Video Processing Front End (VPFE) is a key component for image capture
+applications. The capture module provides the system interface and the
+processing capability to connect RAW image-sensor modules and video decoders
+to the AM437x device.
+
+Required properties:
+- compatible: must be "ti,am437x-vpfe"
+- reg: physical base address and length of the registers set for the device;
+- interrupts: should contain IRQ line for the VPFE;
+- ti,am437x-vpfe-interface: can be one of the following,
+	0 - Raw Bayer Interface.
+	1 - 8 Bit BT656 Interface.
+	2 - 10 Bit BT656 Interface.
+	3 - YCbCr 8 Bit Interface.
+	4 - YCbCr 16 Bit Interface.
+
+VPFE supports a single port node with parallel bus. It should contain one
+'port' child node with child 'endpoint' node. Please refer to the bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+	vpfe: vpfe@f0034000 {
+		compatible = "ti,am437x-vpfe";
+		reg = <0x48328000 0x2000>;
+		interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&vpfe_pins_default>;
+		pinctrl-1 = <&vpfe_pins_sleep>;
+
+		port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vpfe0_ep: endpoint {
+				remote-endpoint = <&ov2659_1>;
+				ti,am437x-vpfe-interface = <0>;
+				bus-width = <8>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+			};
+		};
+	};
+
+	i2c1: i2c@4802a000 {
+
+		ov2659@30 {
+			compatible = "ti,ov2659";
+			reg = <0x30>;
+
+			port {
+				ov2659_1: endpoint {
+					remote-endpoint = <&vpfe0_ep>;
+					bus-width = <8>;
+					mclk-frequency = <12000000>;
+				};
+			};
+	};
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt
index ce719f89dd1c..52a14cf099ac 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.txt
+++ b/Documentation/devicetree/bindings/media/video-interfaces.txt
@@ -103,6 +103,9 @@ Optional endpoint properties
   array contains only one entry.
 - clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
   clock mode.
+- link-frequencies: Allowed data bus frequencies. For MIPI CSI-2, for
+  instance, this is the actual frequency of the bus, not bits per clock per
+  lane value. An array of 64-bit unsigned integers.
 
 
 Example
diff --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt
deleted file mode 100644
index 0b69e4ee8e31..000000000000
--- a/Documentation/video4linux/CQcam.txt
+++ /dev/null
@@ -1,205 +0,0 @@
-c-qcam - Connectix Color QuickCam video4linux kernel driver
-
-Copyright (C) 1999  Dave Forrest  <drf5n@virginia.edu>
-		    released under GNU GPL.
-
-1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind
-
-
-Table of Contents
-
-1.0 Introduction
-2.0 Compilation, Installation, and Configuration
-3.0 Troubleshooting
-4.0 Future Work / current work arounds
-9.0 Sample Program, v4lgrab
-10.0 Other Information
-
-
-1.0 Introduction
-
-  The file ../../drivers/media/parport/c-qcam.c is a device driver for
-the Logitech (nee Connectix) parallel port interface color CCD camera.
-This is a fairly inexpensive device for capturing images.  Logitech
-does not currently provide information for developers, but many people
-have engineered several solutions for non-Microsoft use of the Color
-Quickcam.
-
-1.1 Motivation
-
-  I spent a number of hours trying to get my camera to work, and I
-hope this document saves you some time.  My camera will not work with
-the 2.2.13 kernel as distributed, but with a few patches to the
-module, I was able to grab some frames. See 4.0, Future Work.
-
-
-
-2.0 Compilation, Installation, and Configuration
-
-  The c-qcam depends on parallel port support, video4linux, and the
-Color Quickcam.  It is also nice to have the parallel port readback
-support enabled. I enabled these as modules during the kernel
-configuration.  The appropriate flags are:
-
-    CONFIG_PRINTER       M    for lp.o, parport.o parport_pc.o modules
-    CONFIG_PNP_PARPORT   M for autoprobe.o IEEE1284 readback module
-    CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module
-    CONFIG_VIDEO_DEV     M    for videodev.o video4linux module
-    CONFIG_VIDEO_CQCAM   M    for c-qcam.o  Color Quickcam module
-
-  With these flags, the kernel should compile and install the modules.
-To record and monitor the compilation, I use:
-
- (make zlilo ; \
-  make modules; \
-  make modules_install ;
-  depmod -a ) &>log &
- less log  # then a capital 'F' to watch the progress
-
-But that is my personal preference.
-
-2.2 Configuration
-
-  The configuration requires module configuration and device
-configuration.  The following sections detail these procedures.
-
-
-2.1 Module Configuration
-
-  Using modules requires a bit of work to install and pass the
-parameters.  Understand that entries in /etc/modprobe.d/*.conf of:
-
-   alias parport_lowlevel parport_pc
-   options parport_pc io=0x378 irq=none
-   alias char-major-81 videodev
-   alias char-major-81-0 c-qcam
-
-2.2 Device Configuration
-
-  At this point, we need to ensure that the device files exist.
-Video4linux used the /dev/video* files, and we want to attach the
-Quickcam to one of these.
-
-   ls -lad /dev/video*  # should produce a list of the video devices
-
-If the video devices do not exist, you can create them with:
-
-  su
-  cd /dev
-  for ii in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
-    mknod video$ii c 81 $ii   # char-major-81-[0-16]
-    chown root.root video$ii  # owned by root
-    chmod 600 video$ii        # read/writable by root only
-  done
-
-  Lots of people connect video0 to video and bttv, but you might want
-your c-qcam to mean something more:
-
-   ln -s video0 c-qcam  # make /dev/c-qcam a working file
-   ln -s c-qcam video   # make /dev/c-qcam your default video source
-
-  But these are conveniences.  The important part is to make the proper
-special character files with the right major and minor numbers.  All
-of the special device files are listed in ../devices.txt.  If you
-would like the c-qcam readable by non-root users, you will need to
-change the permissions.
-
-3.0 Troubleshooting
-
-  If the sample program below, v4lgrab, gives you output then
-everything is working.
-
-    v4lgrab | wc # should give you a count of characters
-
-  Otherwise, you have some problem.
-
-  The c-qcam is IEEE1284 compatible, so if you are using the proc file
-system (CONFIG_PROC_FS), the parallel printer support
-(CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you
-should be able to read some identification from your quickcam with
-
-	 modprobe -v parport
-	 modprobe -v parport_probe
-	 cat /proc/parport/PORTNUMBER/autoprobe
-Returns:
-  CLASS:MEDIA;
-  MODEL:Color QuickCam 2.0;
-  MANUFACTURER:Connectix;
-
-  A good response to this indicates that your color quickcam is alive
-and well.  A common problem is that the current driver does not
-reliably detect a c-qcam, even though one is attached.  In this case,
-
-     modprobe -v c-qcam
-or
-     insmod -v c-qcam
-
-  Returns a message saying "Device or resource busy"  Development is
-currently underway, but a workaround is to patch the module to skip
-the detection code and attach to a defined port.  Check the
-video4linux mailing list and archive for more current information.
-
-3.1 Checklist:
-
-  Can you get an image?
-	    v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
-
-  Is a working c-qcam connected to the port?
-	    grep ^ /proc/parport/?/autoprobe
-
-  Do the /dev/video* files exist?
-	    ls -lad /dev/video
-
-  Is the c-qcam module loaded?
-	    modprobe -v c-qcam ; lsmod
-
-  Does the camera work with alternate programs? cqcam, etc?
-
-
-
-
-4.0 Future Work / current workarounds
-
-  It is hoped that this section will soon become obsolete, but if it
-isn't, you might try patching the c-qcam module to add a parport=xxx
-option as in the bw-qcam module so you can specify the parallel port:
-
-       insmod -v c-qcam parport=0
-
-And bypass the detection code, see ../../drivers/char/c-qcam.c and
-look for the 'qc_detect' code and call.
-
-  Note that there is work in progress to change the video4linux API,
-this work is documented at the video4linux2 site listed below.
-
-
-9.0 --- A sample program using v4lgrabber,
-
-v4lgrab is a simple image grabber that will copy a frame from the
-first video device, /dev/video0 to standard output in portable pixmap
-format (.ppm)  To produce .jpg output, you can use it like this:
-'v4lgrab | convert - c-qcam.jpg'
-
-
-10.0 --- Other Information
-
-Use the ../../Maintainers file, particularly the  VIDEO FOR LINUX and PARALLEL
-PORT SUPPORT sections
-
-The video4linux page:
-  http://linuxtv.org
-
-The V4L2 API spec:
-  http://v4l2spec.bytesex.org/
-
-Some web pages about the quickcams:
-   http://www.pingouin-land.com/howto/QuickCam-HOWTO.html
-
-   http://www.crynwr.com/qcpc/            QuickCam Third-Party Drivers
-   http://www.crynwr.com/qcpc/re.html     Some Reverse Engineering
-   http://www.wirelesscouch.net/software/gqcam/   v4l client
-   http://phobos.illtel.denver.co.us/pub/qcread/ doesn't use v4l
-   ftp://ftp.cs.unm.edu/pub/chris/quickcam/   Has lots of drivers
-   http://www.cs.duke.edu/~reynolds/quickcam/ Has lots of information
-
-
diff --git a/Documentation/video4linux/README.tlg2300 b/Documentation/video4linux/README.tlg2300
deleted file mode 100644
index 416ccb93d8c9..000000000000
--- a/Documentation/video4linux/README.tlg2300
+++ /dev/null
@@ -1,47 +0,0 @@
-tlg2300 release notes
-====================
-
-This is a v4l2/dvb device driver for the tlg2300 chip.
-
-
-current status
-==============
-
-video
-	- support mmap and read().(no overlay)
-
-audio
-	- The driver will register a ALSA card for the audio input.
-
-vbi
-	- Works for almost TV norms.
-
-dvb-t
-	- works for DVB-T
-
-FM
-	- Works for radio.
-
----------------------------------------------------------------------------
-TESTED APPLICATIONS:
-
--VLC1.0.4 test the video and dvb. The GUI is friendly to use.
-
--Mplayer test the video.
-
--Mplayer test the FM. The mplayer should be compiled with --enable-radio and
-	 --enable-radio-capture.
-	The command runs as this(The alsa audio registers to card 1):
-	#mplayer radio://103.7/capture/ -radio adevice=hw=1,0:arate=48000 \
-		-rawaudio rate=48000:channels=2
-
----------------------------------------------------------------------------
-KNOWN PROBLEMS:
-about preemphasis:
-	You can set the preemphasis for radio by the following command:
-	#v4l2-ctl -d /dev/radio0 --set-ctrl=pre_emphasis_settings=1
-
-	"pre_emphasis_settings=1" means that you select the 50us. If you want
-	to select the 75us, please use "pre_emphasis_settings=2"
-
-
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index a11dff07ef71..f586e29ce221 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -793,8 +793,10 @@ video_register_device_no_warn() instead.
 
 Whenever a device node is created some attributes are also created for you.
 If you look in /sys/class/video4linux you see the devices. Go into e.g.
-video0 and you will see 'name' and 'index' attributes. The 'name' attribute
-is the 'name' field of the video_device struct.
+video0 and you will see 'name', 'debug' and 'index' attributes. The 'name'
+attribute is the 'name' field of the video_device struct. The 'debug' attribute
+can be used to enable core debugging. See the next section for more detailed
+information on this.
 
 The 'index' attribute is the index of the device node: for each call to
 video_register_device() the index is just increased by 1. The first video
@@ -816,6 +818,25 @@ video_device was embedded in it. The vdev->release() callback will never
 be called if the registration failed, nor should you ever attempt to
 unregister the device if the registration failed.
 
+video device debugging
+----------------------
+
+The 'debug' attribute that is created for each video, vbi, radio or swradio
+device in /sys/class/video4linux/<devX>/ allows you to enable logging of
+file operations.
+
+It is a bitmask and the following bits can be set:
+
+0x01: Log the ioctl name and error code. VIDIOC_(D)QBUF ioctls are only logged
+      if bit 0x08 is also set.
+0x02: Log the ioctl name arguments and error code. VIDIOC_(D)QBUF ioctls are
+      only logged if bit 0x08 is also set.
+0x04: Log the file operations open, release, read, write, mmap and
+      get_unmapped_area. The read and write operations are only logged if
+      bit 0x08 is also set.
+0x08: Log the read and write file operations and the VIDIOC_QBUF and
+      VIDIOC_DQBUF ioctls.
+0x10: Log the poll file operation.
 
 video_device cleanup
 --------------------
diff --git a/Documentation/video4linux/w9966.txt b/Documentation/video4linux/w9966.txt
deleted file mode 100644
index 855024525fd2..000000000000
--- a/Documentation/video4linux/w9966.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-W9966 Camera driver, written by Jakob Kemi (jakob.kemi@telia.com)
-
-After a lot of work in softice & wdasm, reading .pdf-files and tiresome
-trial-and-error work I've finally got everything to work. I needed vision for a
-robotics project so I borrowed this camera from a friend and started hacking.
-Anyway I've converted my original code from the AVR 8bit RISC C/ASM code into
-a working Linux driver.
-
-To get it working simply configure your kernel to support
-parport, ieee1284, video4linux and w9966
-
-If w9966 is statically linked it will always perform aggressive probing for
-the camera. If built as a module you'll have more configuration options.
-
-Options:
- modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
-voila!
-
-you can also type 'modinfo -p w9966.o' for option usage
-(or checkout w9966.c)
-
-The only thing to keep in mind is that the image format is in Y-U-Y-V format
-where every two pixels take 4 bytes. In SDL (www.libsdl.org) this format
-is called VIDEO_PALETTE_YUV422 (16 bpp).
-
-A minimal test application (with source) is available from:
-  http://www.slackwaresupport.com/howtos/Webcam-HOWTO
-
-The slow framerate is due to missing DMA ECP read support in the
-parport drivers. I might add working EPP support later.
-
-Good luck!
-    /Jakob Kemi
diff --git a/MAINTAINERS b/MAINTAINERS
index d3f826f4cabd..8726ac5d7cec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -659,6 +659,13 @@ L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	drivers/media/i2c/ad9389b*
 
+ANALOG DEVICES INC ADV7180 DRIVER
+M:	Lars-Peter Clausen <lars@metafoo.de>
+L:	linux-media@vger.kernel.org
+W:	http://ez.analog.com/community/linux-device-drivers
+S:	Supported
+F:	drivers/media/i2c/adv7180.c
+
 ANALOG DEVICES INC ADV7511 DRIVER
 M:	Hans Verkuil <hans.verkuil@cisco.com>
 L:	linux-media@vger.kernel.org
@@ -6202,14 +6209,6 @@ F:	include/uapi/linux/meye.h
 F:	include/uapi/linux/ivtv*
 F:	include/uapi/linux/uvcvideo.h
 
-MEDIAVISION PRO MOVIE STUDIO DRIVER
-M:	Hans Verkuil <hverkuil@xs4all.nl>
-L:	linux-media@vger.kernel.org
-T:	git git://linuxtv.org/media_tree.git
-W:	http://linuxtv.org
-S:	Odd Fixes
-F:	drivers/media/parport/pms*
-
 MEGARAID SCSI/SAS DRIVERS
 M:	Kashyap Desai <kashyap.desai@avagotech.com>
 M:	Sumit Saxena <sumit.saxena@avagotech.com>
@@ -7909,14 +7908,6 @@ T:	git git://github.com/KrasnikovEugene/wcn36xx.git
 S:	Supported
 F:	drivers/net/wireless/ath/wcn36xx/
 
-QUICKCAM PARALLEL PORT WEBCAMS
-M:	Hans Verkuil <hverkuil@xs4all.nl>
-L:	linux-media@vger.kernel.org
-T:	git git://linuxtv.org/media_tree.git
-W:	http://linuxtv.org
-S:	Odd Fixes
-F:	drivers/media/parport/*-qcam*
-
 RADOS BLOCK DEVICE (RBD)
 M:	Yehuda Sadeh <yehuda@inktank.com>
 M:	Sage Weil <sage@inktank.com>
@@ -8454,12 +8445,6 @@ F:	kernel/time/clocksource.c
 F:	kernel/time/time*.c
 F:	kernel/time/ntp.c
 
-TLG2300 VIDEO4LINUX-2 DRIVER
-M:	Huang Shijie <shijie8@gmail.com>
-M:	Hans Verkuil <hverkuil@xs4all.nl>
-S:	Odd Fixes
-F:	drivers/media/usb/tlg2300/
-
 SC1200 WDT DRIVER
 M:	Zwane Mwaikambo <zwanem@gmail.com>
 S:	Maintained
@@ -8825,6 +8810,15 @@ S:	Maintained
 F:	drivers/media/platform/davinci/
 F:	include/media/davinci/
 
+TI AM437X VPFE DRIVER
+M:	Lad, Prabhakar <prabhakar.csengg@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
+S:	Maintained
+F:	drivers/media/platform/am437x/
+
 SIS 190 ETHERNET DRIVER
 M:	Francois Romieu <romieu@fr.zoreil.com>
 L:	netdev@vger.kernel.org
@@ -8906,6 +8900,8 @@ F:	drivers/media/i2c/smiapp/
 F:	include/media/smiapp.h
 F:	drivers/media/i2c/smiapp-pll.c
 F:	drivers/media/i2c/smiapp-pll.h
+F:	include/uapi/linux/smiapp.h
+F:	Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
 
 SMM665 HARDWARE MONITOR DRIVER
 M:	Guenter Roeck <linux@roeck-us.net>
@@ -8972,6 +8968,7 @@ SOFTLOGIC 6x10 MPEG CODEC
 M:	Bluecherry Maintainers <maintainers@bluecherrydvr.com>
 M:	Andrey Utkin <andrey.utkin@corp.bluecherry.net>
 M:	Andrey Utkin <andrey.krieger.utkin@gmail.com>
+M:	Ismael Luceno <ismael@iodev.co.uk>
 L:	linux-media@vger.kernel.org
 S:	Supported
 F:	drivers/media/pci/solo6x10/
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index b85f88c8ddbd..21154dd87b0b 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -8,10 +8,6 @@ comment "common driver options"
 config VIDEO_CX2341X
 	tristate
 
-config VIDEO_BTCX
-	depends on PCI
-	tristate
-
 config VIDEO_TVEEPROM
 	tristate
 	depends on I2C
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
index d208de3b7cc0..89b795df2cdd 100644
--- a/drivers/media/common/Makefile
+++ b/drivers/media/common/Makefile
@@ -1,5 +1,4 @@
 obj-y += b2c2/ saa7146/ siano/
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
-obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
 obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o
diff --git a/drivers/media/common/btcx-risc.h b/drivers/media/common/btcx-risc.h
index f8bc6e8e7b51..03583ef90506 100644
--- a/drivers/media/common/btcx-risc.h
+++ b/drivers/media/common/btcx-risc.h
@@ -26,9 +26,3 @@ void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
 void btcx_calc_skips(int line, int width, int *maxy,
 		     struct btcx_skiplist *skips, unsigned int *nskips,
 		     const struct v4l2_clip *clips, unsigned int nclips);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index e4041f074909..686d3277dad1 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -68,13 +68,6 @@
 #include "dvb_demux.h"
 #include "dvb_net.h"
 
-static int dvb_net_debug;
-module_param(dvb_net_debug, int, 0444);
-MODULE_PARM_DESC(dvb_net_debug, "enable debug messages");
-
-#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0)
-
-
 static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 {
 	unsigned int j;
@@ -90,36 +83,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 
 #ifdef ULE_DEBUG
 
-#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
-#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
-
-#define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
-
-static void hexdump( const unsigned char *buf, unsigned short len )
+static void hexdump(const unsigned char *buf, unsigned short len)
 {
-	char str[80], octet[10];
-	int ofs, i, l;
-
-	for (ofs = 0; ofs < len; ofs += 16) {
-		sprintf( str, "%03d: ", ofs );
-
-		for (i = 0; i < 16; i++) {
-			if ((i + ofs) < len)
-				sprintf( octet, "%02x ", buf[ofs + i] );
-			else
-				strcpy( octet, "   " );
-
-			strcat( str, octet );
-		}
-		strcat( str, "  " );
-		l = strlen( str );
-
-		for (i = 0; (i < 16) && ((i + ofs) < len); i++)
-			str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.';
-
-		str[l] = '\0';
-		printk( KERN_WARNING "%s\n", str );
-	}
+	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
 }
 
 #endif
@@ -315,9 +281,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
 			return l;	/* Stop extension header processing and discard SNDU. */
 		total_ext_len += l;
 #ifdef ULE_DEBUG
-		dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
-			"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
-			(int) p->ule_sndu_type, l, total_ext_len);
+		pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n",
+			 p->ule_next_hdr, (int)p->ule_sndu_type,
+			 l, total_ext_len);
 #endif
 
 	} while (p->ule_sndu_type < ETH_P_802_3_MIN);
@@ -700,8 +666,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 
 					if (drop) {
 #ifdef ULE_DEBUG
-						dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
-							MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
+						netdev_dbg(dev, "Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n",
+							   priv->ule_skb->data, dev->dev_addr);
 #endif
 						dev_kfree_skb(priv->ule_skb);
 						goto sndu_done;
@@ -964,8 +930,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev,
 	(*secfilter)->filter_mask[10] = mac_mask[1];
 	(*secfilter)->filter_mask[11]=mac_mask[0];
 
-	dprintk("%s: filter mac=%pM\n", dev->name, mac);
-	dprintk("%s: filter mask=%pM\n", dev->name, mac_mask);
+	netdev_dbg(dev, "filter mac=%pM mask=%pM\n", mac, mac_mask);
 
 	return 0;
 }
@@ -977,7 +942,7 @@ static int dvb_net_feed_start(struct net_device *dev)
 	struct dmx_demux *demux = priv->demux;
 	unsigned char *mac = (unsigned char *) dev->dev_addr;
 
-	dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
+	netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
 	mutex_lock(&priv->mutex);
 	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
 		printk("%s: BUG %d\n", __func__, __LINE__);
@@ -987,7 +952,7 @@ static int dvb_net_feed_start(struct net_device *dev)
 	priv->tsfeed = NULL;
 
 	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
-		dprintk("%s: alloc secfeed\n", __func__);
+		netdev_dbg(dev, "alloc secfeed\n");
 		ret=demux->allocate_section_feed(demux, &priv->secfeed,
 					 dvb_net_sec_callback);
 		if (ret<0) {
@@ -1005,38 +970,38 @@ static int dvb_net_feed_start(struct net_device *dev)
 		}
 
 		if (priv->rx_mode != RX_MODE_PROMISC) {
-			dprintk("%s: set secfilter\n", __func__);
+			netdev_dbg(dev, "set secfilter\n");
 			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
 		}
 
 		switch (priv->rx_mode) {
 		case RX_MODE_MULTI:
 			for (i = 0; i < priv->multi_num; i++) {
-				dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
+				netdev_dbg(dev, "set multi_secfilter[%d]\n", i);
 				dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
 						       priv->multi_macs[i], mask_normal);
 			}
 			break;
 		case RX_MODE_ALL_MULTI:
 			priv->multi_num=1;
-			dprintk("%s: set multi_secfilter[0]\n", __func__);
+			netdev_dbg(dev, "set multi_secfilter[0]\n");
 			dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
 					       mac_allmulti, mask_allmulti);
 			break;
 		case RX_MODE_PROMISC:
 			priv->multi_num=0;
-			dprintk("%s: set secfilter\n", __func__);
+			netdev_dbg(dev, "set secfilter\n");
 			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
 			break;
 		}
 
-		dprintk("%s: start filtering\n", __func__);
+		netdev_dbg(dev, "start filtering\n");
 		priv->secfeed->start_filtering(priv->secfeed);
 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
 		struct timespec timeout = { 0, 10000000 }; // 10 msec
 
 		/* we have payloads encapsulated in TS */
-		dprintk("%s: alloc tsfeed\n", __func__);
+		netdev_dbg(dev, "alloc tsfeed\n");
 		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
 		if (ret < 0) {
 			printk("%s: could not allocate ts feed\n", dev->name);
@@ -1060,7 +1025,7 @@ static int dvb_net_feed_start(struct net_device *dev)
 			goto error;
 		}
 
-		dprintk("%s: start filtering\n", __func__);
+		netdev_dbg(dev, "start filtering\n");
 		priv->tsfeed->start_filtering(priv->tsfeed);
 	} else
 		ret = -EINVAL;
@@ -1075,17 +1040,16 @@ static int dvb_net_feed_stop(struct net_device *dev)
 	struct dvb_net_priv *priv = netdev_priv(dev);
 	int i, ret = 0;
 
-	dprintk("%s\n", __func__);
 	mutex_lock(&priv->mutex);
 	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
 		if (priv->secfeed) {
 			if (priv->secfeed->is_filtering) {
-				dprintk("%s: stop secfeed\n", __func__);
+				netdev_dbg(dev, "stop secfeed\n");
 				priv->secfeed->stop_filtering(priv->secfeed);
 			}
 
 			if (priv->secfilter) {
-				dprintk("%s: release secfilter\n", __func__);
+				netdev_dbg(dev, "release secfilter\n");
 				priv->secfeed->release_filter(priv->secfeed,
 							      priv->secfilter);
 				priv->secfilter=NULL;
@@ -1093,8 +1057,8 @@ static int dvb_net_feed_stop(struct net_device *dev)
 
 			for (i=0; i<priv->multi_num; i++) {
 				if (priv->multi_secfilter[i]) {
-					dprintk("%s: release multi_filter[%d]\n",
-						__func__, i);
+					netdev_dbg(dev, "release multi_filter[%d]\n",
+						   i);
 					priv->secfeed->release_filter(priv->secfeed,
 								      priv->multi_secfilter[i]);
 					priv->multi_secfilter[i] = NULL;
@@ -1108,7 +1072,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
 		if (priv->tsfeed) {
 			if (priv->tsfeed->is_filtering) {
-				dprintk("%s: stop tsfeed\n", __func__);
+				netdev_dbg(dev, "stop tsfeed\n");
 				priv->tsfeed->stop_filtering(priv->tsfeed);
 			}
 			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
@@ -1148,16 +1112,16 @@ static void wq_set_multicast_list (struct work_struct *work)
 	netif_addr_lock_bh(dev);
 
 	if (dev->flags & IFF_PROMISC) {
-		dprintk("%s: promiscuous mode\n", dev->name);
+		netdev_dbg(dev, "promiscuous mode\n");
 		priv->rx_mode = RX_MODE_PROMISC;
 	} else if ((dev->flags & IFF_ALLMULTI)) {
-		dprintk("%s: allmulti mode\n", dev->name);
+		netdev_dbg(dev, "allmulti mode\n");
 		priv->rx_mode = RX_MODE_ALL_MULTI;
 	} else if (!netdev_mc_empty(dev)) {
 		struct netdev_hw_addr *ha;
 
-		dprintk("%s: set_mc_list, %d entries\n",
-			dev->name, netdev_mc_count(dev));
+		netdev_dbg(dev, "set_mc_list, %d entries\n",
+			   netdev_mc_count(dev));
 
 		priv->rx_mode = RX_MODE_MULTI;
 		priv->multi_num = 0;
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 6c75418222e2..bb76727d924e 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -443,7 +443,8 @@ config DVB_CXD2820R
 
 config DVB_RTL2830
 	tristate "Realtek RTL2830 DVB-T"
-	depends on DVB_CORE && I2C
+	depends on DVB_CORE && I2C && I2C_MUX
+	select REGMAP
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y when you want to support this frontend.
@@ -451,6 +452,7 @@ config DVB_RTL2830
 config DVB_RTL2832
 	tristate "Realtek RTL2832 DVB-T"
 	depends on DVB_CORE && I2C && I2C_MUX
+	select REGMAP
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
index 83fe9a615619..612251958855 100644
--- a/drivers/media/dvb-frontends/au8522.h
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -91,8 +91,3 @@ enum au8522_audio_input {
 };
 
 #endif /* __AU8522_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 61e31f2d2f71..8c6663b6399d 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -1263,7 +1263,8 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
 	struct dib8000_state *state = fe->demodulator_priv;
 	enum frontend_tune_state *tune_state = &state->tune_state;
 	int ret = 0;
-	u16 reg, upd_demod_gain_period = 0x8000;
+	u16 reg;
+	u32 upd_demod_gain_period = 0x8000;
 
 	switch (*tune_state) {
 	case CT_AGC_START:
diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c
index d7b9d549156d..67c8e6df42e8 100644
--- a/drivers/media/dvb-frontends/hd29l2.c
+++ b/drivers/media/dvb-frontends/hd29l2.c
@@ -22,20 +22,24 @@
 
 #include "hd29l2_priv.h"
 
+#define HD29L2_MAX_LEN (3)
+
 /* write multiple registers */
 static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
 {
 	int ret;
-	u8 buf[2 + len];
+	u8 buf[2 + HD29L2_MAX_LEN];
 	struct i2c_msg msg[1] = {
 		{
 			.addr = priv->cfg.i2c_addr,
 			.flags = 0,
-			.len = sizeof(buf),
+			.len = 2 + len,
 			.buf = buf,
 		}
 	};
 
+	if (len > HD29L2_MAX_LEN)
+		return -EINVAL;
 	buf[0] = 0x00;
 	buf[1] = reg;
 	memcpy(&buf[2], val, len);
@@ -118,7 +122,7 @@ static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask)
 }
 
 /* read single register with mask */
-int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
+static int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
 {
 	int ret, i;
 	u8 tmp;
diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c
index 5fd14f840ab0..99efeba3c31a 100644
--- a/drivers/media/dvb-frontends/lg2160.c
+++ b/drivers/media/dvb-frontends/lg2160.c
@@ -1456,9 +1456,3 @@ MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.3");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c
index 92c891a571ab..d08570af1c10 100644
--- a/drivers/media/dvb-frontends/lgdt3305.c
+++ b/drivers/media/dvb-frontends/lgdt3305.c
@@ -236,12 +236,13 @@ static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,
 	return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
 }
 
-static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
-				       enum lgdt3305_tp_clock_edge edge,
-				       enum lgdt3305_tp_valid_polarity valid)
+static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state)
 {
 	u8 val;
 	int ret;
+	enum lgdt3305_tp_clock_edge edge = state->cfg->tpclk_edge;
+	enum lgdt3305_tp_clock_mode mode = state->cfg->tpclk_mode;
+	enum lgdt3305_tp_valid_polarity valid = state->cfg->tpvalid_polarity;
 
 	lg_dbg("edge = %d, valid = %d\n", edge, valid);
 
@@ -253,6 +254,8 @@ static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
 
 	if (edge)
 		val |= 0x08;
+	if (mode)
+		val |= 0x40;
 	if (valid)
 		val |= 0x01;
 
@@ -740,9 +743,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe)
 		goto fail;
 
 	/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
-	ret = lgdt3305_mpeg_mode_polarity(state,
-					  state->cfg->tpclk_edge,
-					  state->cfg->tpvalid_polarity);
+	ret = lgdt3305_mpeg_mode_polarity(state);
 fail:
 	return ret;
 }
@@ -806,9 +807,7 @@ static int lgdt3305_set_parameters(struct dvb_frontend *fe)
 		goto fail;
 
 	/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
-	ret = lgdt3305_mpeg_mode_polarity(state,
-					  state->cfg->tpclk_edge,
-					  state->cfg->tpvalid_polarity);
+	ret = lgdt3305_mpeg_mode_polarity(state);
 fail:
 	return ret;
 }
@@ -1215,9 +1214,3 @@ MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.2");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/lgdt3305.h b/drivers/media/dvb-frontends/lgdt3305.h
index d9ab556c1b27..9c03e530e01b 100644
--- a/drivers/media/dvb-frontends/lgdt3305.h
+++ b/drivers/media/dvb-frontends/lgdt3305.h
@@ -37,6 +37,11 @@ enum lgdt3305_tp_clock_edge {
 	LGDT3305_TPCLK_FALLING_EDGE = 1,
 };
 
+enum lgdt3305_tp_clock_mode {
+	LGDT3305_TPCLK_GATED = 0,
+	LGDT3305_TPCLK_FIXED = 1,
+};
+
 enum lgdt3305_tp_valid_polarity {
 	LGDT3305_TP_VALID_LOW = 0,
 	LGDT3305_TP_VALID_HIGH = 1,
@@ -70,6 +75,7 @@ struct lgdt3305_config {
 
 	enum lgdt3305_mpeg_mode mpeg_mode;
 	enum lgdt3305_tp_clock_edge tpclk_edge;
+	enum lgdt3305_tp_clock_mode tpclk_mode;
 	enum lgdt3305_tp_valid_polarity tpvalid_polarity;
 	enum lgdt_demod_chip_type demod_chip;
 };
diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c
index e046622df0e4..2e1a61893fc1 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -823,9 +823,3 @@ MODULE_AUTHOR("Wilson Michaels");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(lgdt330x_attach);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/lgdt330x.h b/drivers/media/dvb-frontends/lgdt330x.h
index ca0eab562e1e..8bb332219fc4 100644
--- a/drivers/media/dvb-frontends/lgdt330x.h
+++ b/drivers/media/dvb-frontends/lgdt330x.h
@@ -65,9 +65,3 @@ static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config*
 #endif // CONFIG_DVB_LGDT330X
 
 #endif /* LGDT330X_H */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/lgdt330x_priv.h b/drivers/media/dvb-frontends/lgdt330x_priv.h
index 38c76695abfe..1922f09a02d0 100644
--- a/drivers/media/dvb-frontends/lgdt330x_priv.h
+++ b/drivers/media/dvb-frontends/lgdt330x_priv.h
@@ -69,9 +69,3 @@ enum I2C_REG {
 };
 
 #endif /* _LGDT330X_PRIV_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index e6f165a5b90d..8f54c39ca63f 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -22,10 +22,6 @@
 
 #define NUM_LAYERS 3
 
-static int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
 enum mb86a20s_bandwidth {
 	MB86A20S_13SEG = 0,
 	MB86A20S_13SEG_PARTIAL = 1,
diff --git a/drivers/media/dvb-frontends/mn88472.h b/drivers/media/dvb-frontends/mn88472.h
index da4558bce60f..e4e0b80d3091 100644
--- a/drivers/media/dvb-frontends/mn88472.h
+++ b/drivers/media/dvb-frontends/mn88472.h
@@ -33,6 +33,12 @@ struct mn88472_config {
 	 * DVB frontend.
 	 */
 	struct dvb_frontend **fe;
+
+	/*
+	 * Xtal frequency.
+	 * Hz
+	 */
+	u32 xtal;
 };
 
 #endif
diff --git a/drivers/media/dvb-frontends/nxt200x.h b/drivers/media/dvb-frontends/nxt200x.h
index b518d545609e..e38d01fb6c2b 100644
--- a/drivers/media/dvb-frontends/nxt200x.h
+++ b/drivers/media/dvb-frontends/nxt200x.h
@@ -55,9 +55,3 @@ static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* c
 #endif // CONFIG_DVB_NXT200X
 
 #endif /* NXT200X_H */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c
index 5ef921823c15..cbbd259eacfe 100644
--- a/drivers/media/dvb-frontends/or51132.c
+++ b/drivers/media/dvb-frontends/or51132.c
@@ -623,9 +623,3 @@ MODULE_AUTHOR("Trent Piepho");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(or51132_attach);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/or51132.h b/drivers/media/dvb-frontends/or51132.h
index 938958386cb1..cdb5be3c65d6 100644
--- a/drivers/media/dvb-frontends/or51132.h
+++ b/drivers/media/dvb-frontends/or51132.h
@@ -47,9 +47,3 @@ static inline struct dvb_frontend* or51132_attach(const struct or51132_config* c
 #endif // CONFIG_DVB_OR51132
 
 #endif // OR51132_H
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
index 50e8b63e5169..e1b8df62bd59 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -13,261 +13,154 @@
  *    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.
- */
-
-
-/*
- * Driver implements own I2C-adapter for tuner I2C access. That's since chip
- * have unusual I2C-gate control which closes gate automatically after each
- * I2C transfer. Using own I2C adapter we can workaround that.
  */
 
 #include "rtl2830_priv.h"
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
-
-/* write multiple hardware registers */
-static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len)
+/* Our regmap is bypassing I2C adapter lock, thus we do it! */
+static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg,
+			      const void *val, size_t val_count)
 {
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	u8 buf[MAX_XFER_SIZE];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1 + len,
-			.buf = buf,
-		}
-	};
-
-	if (1 + len > sizeof(buf)) {
-		dev_warn(&priv->i2c->dev,
-			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
-			 KBUILD_MODNAME, reg, len);
-		return -EINVAL;
-	}
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
 
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
-				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
+	i2c_lock_adapter(client->adapter);
+	ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
+	i2c_unlock_adapter(client->adapter);
 	return ret;
 }
 
-/* read multiple hardware registers */
-static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
+static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg,
+			       unsigned int mask, unsigned int val)
 {
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
 
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
-				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
+	i2c_lock_adapter(client->adapter);
+	ret = regmap_update_bits(dev->regmap, reg, mask, val);
+	i2c_unlock_adapter(client->adapter);
 	return ret;
 }
 
-/* write multiple registers */
-static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val,
-		int len)
+static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg,
+			     void *val, size_t val_count)
 {
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 page = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2830_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-	}
-
-	return rtl2830_wr(priv, reg2, val, len);
-}
-
-/* read multiple registers */
-static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
-{
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 page = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2830_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-	}
 
-	return rtl2830_rd(priv, reg2, val, len);
-}
-
-/* read single register */
-static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
-{
-	return rtl2830_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-static int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return rtl2830_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register with mask */
-static int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
+	i2c_lock_adapter(client->adapter);
+	ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
+	i2c_unlock_adapter(client->adapter);
+	return ret;
 }
 
 static int rtl2830_init(struct dvb_frontend *fe)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
+	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
 	int ret, i;
 	struct rtl2830_reg_val_mask tab[] = {
-		{ 0x00d, 0x01, 0x03 },
-		{ 0x00d, 0x10, 0x10 },
-		{ 0x104, 0x00, 0x1e },
-		{ 0x105, 0x80, 0x80 },
-		{ 0x110, 0x02, 0x03 },
-		{ 0x110, 0x08, 0x0c },
-		{ 0x17b, 0x00, 0x40 },
-		{ 0x17d, 0x05, 0x0f },
-		{ 0x17d, 0x50, 0xf0 },
-		{ 0x18c, 0x08, 0x0f },
-		{ 0x18d, 0x00, 0xc0 },
-		{ 0x188, 0x05, 0x0f },
-		{ 0x189, 0x00, 0xfc },
-		{ 0x2d5, 0x02, 0x02 },
-		{ 0x2f1, 0x02, 0x06 },
-		{ 0x2f1, 0x20, 0xf8 },
-		{ 0x16d, 0x00, 0x01 },
-		{ 0x1a6, 0x00, 0x80 },
-		{ 0x106, priv->cfg.vtop, 0x3f },
-		{ 0x107, priv->cfg.krf, 0x3f },
-		{ 0x112, 0x28, 0xff },
-		{ 0x103, priv->cfg.agc_targ_val, 0xff },
-		{ 0x00a, 0x02, 0x07 },
-		{ 0x140, 0x0c, 0x3c },
-		{ 0x140, 0x40, 0xc0 },
-		{ 0x15b, 0x05, 0x07 },
-		{ 0x15b, 0x28, 0x38 },
-		{ 0x15c, 0x05, 0x07 },
-		{ 0x15c, 0x28, 0x38 },
-		{ 0x115, priv->cfg.spec_inv, 0x01 },
-		{ 0x16f, 0x01, 0x07 },
-		{ 0x170, 0x18, 0x38 },
-		{ 0x172, 0x0f, 0x0f },
-		{ 0x173, 0x08, 0x38 },
-		{ 0x175, 0x01, 0x07 },
-		{ 0x176, 0x00, 0xc0 },
+		{0x00d, 0x01, 0x03},
+		{0x00d, 0x10, 0x10},
+		{0x104, 0x00, 0x1e},
+		{0x105, 0x80, 0x80},
+		{0x110, 0x02, 0x03},
+		{0x110, 0x08, 0x0c},
+		{0x17b, 0x00, 0x40},
+		{0x17d, 0x05, 0x0f},
+		{0x17d, 0x50, 0xf0},
+		{0x18c, 0x08, 0x0f},
+		{0x18d, 0x00, 0xc0},
+		{0x188, 0x05, 0x0f},
+		{0x189, 0x00, 0xfc},
+		{0x2d5, 0x02, 0x02},
+		{0x2f1, 0x02, 0x06},
+		{0x2f1, 0x20, 0xf8},
+		{0x16d, 0x00, 0x01},
+		{0x1a6, 0x00, 0x80},
+		{0x106, dev->pdata->vtop, 0x3f},
+		{0x107, dev->pdata->krf, 0x3f},
+		{0x112, 0x28, 0xff},
+		{0x103, dev->pdata->agc_targ_val, 0xff},
+		{0x00a, 0x02, 0x07},
+		{0x140, 0x0c, 0x3c},
+		{0x140, 0x40, 0xc0},
+		{0x15b, 0x05, 0x07},
+		{0x15b, 0x28, 0x38},
+		{0x15c, 0x05, 0x07},
+		{0x15c, 0x28, 0x38},
+		{0x115, dev->pdata->spec_inv, 0x01},
+		{0x16f, 0x01, 0x07},
+		{0x170, 0x18, 0x38},
+		{0x172, 0x0f, 0x0f},
+		{0x173, 0x08, 0x38},
+		{0x175, 0x01, 0x07},
+		{0x176, 0x00, 0xc0},
 	};
 
 	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
-			tab[i].mask);
+		ret = rtl2830_update_bits(client, tab[i].reg, tab[i].mask,
+					  tab[i].val);
 		if (ret)
 			goto err;
 	}
 
-	ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
+	ret = rtl2830_bulk_write(client, 0x18f, "\x28\x00", 2);
 	if (ret)
 		goto err;
 
-	ret = rtl2830_wr_regs(priv, 0x195,
-		"\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
+	ret = rtl2830_bulk_write(client, 0x195,
+				 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
 	if (ret)
 		goto err;
 
 	/* TODO: spec init */
 
 	/* soft reset */
-	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
+	ret = rtl2830_update_bits(client, 0x101, 0x04, 0x04);
 	if (ret)
 		goto err;
 
-	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
+	ret = rtl2830_update_bits(client, 0x101, 0x04, 0x00);
 	if (ret)
 		goto err;
 
-	priv->sleeping = false;
+	/* init stats here in order signal app which stats are supported */
+	c->strength.len = 1;
+	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->cnr.len = 1;
+	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_error.len = 1;
+	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_count.len = 1;
+	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	/* start statistics polling */
+	schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
+
+	dev->sleeping = false;
 
 	return ret;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2830_sleep(struct dvb_frontend *fe)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	priv->sleeping = true;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
+
+	dev->sleeping = true;
+	/* stop statistics polling */
+	cancel_delayed_work_sync(&dev->stat_work);
+	dev->fe_status = 0;
+
 	return 0;
 }
 
 static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
+				     struct dvb_frontend_tune_settings *s)
 {
 	s->min_delay_ms = 500;
 	s->step_size = fe->ops.info.frequency_stepsize * 2;
@@ -278,11 +171,12 @@ static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
 
 static int rtl2830_set_frontend(struct dvb_frontend *fe)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i;
 	u64 num;
-	u8 buf[3], tmp;
+	u8 buf[3], u8tmp;
 	u32 if_ctl, if_frequency;
 	static const u8 bw_params1[3][34] = {
 		{
@@ -308,9 +202,8 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
 		{0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
 	};
 
-	dev_dbg(&priv->i2c->dev,
-			"%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
-			__func__, c->frequency, c->bandwidth_hz, c->inversion);
+	dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
+		c->frequency, c->bandwidth_hz, c->inversion);
 
 	/* program tuner */
 	if (fe->ops.tuner_ops.set_params)
@@ -327,11 +220,12 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
 		i = 2;
 		break;
 	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
+		dev_err(&client->dev, "invalid bandwidth_hz %u\n",
+			c->bandwidth_hz);
 		return -EINVAL;
 	}
 
-	ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
+	ret = rtl2830_update_bits(client, 0x008, 0x06, i << 1);
 	if (ret)
 		goto err;
 
@@ -340,70 +234,71 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
 		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
 	else
 		ret = -EINVAL;
-
-	if (ret < 0)
+	if (ret)
 		goto err;
 
-	num = if_frequency % priv->cfg.xtal;
+	num = if_frequency % dev->pdata->clk;
 	num *= 0x400000;
-	num = div_u64(num, priv->cfg.xtal);
+	num = div_u64(num, dev->pdata->clk);
 	num = -num;
 	if_ctl = num & 0x3fffff;
-	dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n",
-			__func__, if_frequency, if_ctl);
+	dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n",
+		if_frequency, if_ctl);
 
-	ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
+	buf[0] = (if_ctl >> 16) & 0x3f;
+	buf[1] = (if_ctl >>  8) & 0xff;
+	buf[2] = (if_ctl >>  0) & 0xff;
+
+	ret = rtl2830_bulk_read(client, 0x119, &u8tmp, 1);
 	if (ret)
 		goto err;
 
-	buf[0] = tmp << 6;
-	buf[0] |= (if_ctl >> 16) & 0x3f;
-	buf[1] = (if_ctl >>  8) & 0xff;
-	buf[2] = (if_ctl >>  0) & 0xff;
+	buf[0] |= u8tmp & 0xc0;  /* [7:6] */
 
-	ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
+	ret = rtl2830_bulk_write(client, 0x119, buf, 3);
 	if (ret)
 		goto err;
 
 	/* 1/2 split I2C write */
-	ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
+	ret = rtl2830_bulk_write(client, 0x11c, &bw_params1[i][0], 17);
 	if (ret)
 		goto err;
 
 	/* 2/2 split I2C write */
-	ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
+	ret = rtl2830_bulk_write(client, 0x12d, &bw_params1[i][17], 17);
 	if (ret)
 		goto err;
 
-	ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
+	ret = rtl2830_bulk_write(client, 0x19d, bw_params2[i], 6);
 	if (ret)
 		goto err;
 
 	return ret;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2830_get_frontend(struct dvb_frontend *fe)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 	u8 buf[3];
 
-	if (priv->sleeping)
+	if (dev->sleeping)
 		return 0;
 
-	ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
+	ret = rtl2830_bulk_read(client, 0x33c, buf, 2);
 	if (ret)
 		goto err;
 
-	ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
+	ret = rtl2830_bulk_read(client, 0x351, &buf[2], 1);
 	if (ret)
 		goto err;
 
-	dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
+	dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
 
 	switch ((buf[0] >> 2) & 3) {
 	case 0:
@@ -493,280 +388,543 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe)
 
 	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	u8 tmp;
+	u8 u8tmp;
+
 	*status = 0;
 
-	if (priv->sleeping)
+	if (dev->sleeping)
 		return 0;
 
-	ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
+	ret = rtl2830_bulk_read(client, 0x351, &u8tmp, 1);
 	if (ret)
 		goto err;
 
-	if (tmp == 11) {
+	u8tmp = (u8tmp >> 3) & 0x0f; /* [6:3] */
+	if (u8tmp == 11) {
 		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	} else if (tmp == 10) {
+	} else if (u8tmp == 10) {
 		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 			FE_HAS_VITERBI;
 	}
 
+	dev->fe_status = *status;
+
 	return ret;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	int ret, hierarchy, constellation;
-	u8 buf[2], tmp;
-	u16 tmp16;
-#define CONSTELLATION_NUM 3
-#define HIERARCHY_NUM 4
-	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
-		{ 70705899, 70705899, 70705899, 70705899 },
-		{ 82433173, 82433173, 87483115, 94445660 },
-		{ 92888734, 92888734, 95487525, 99770748 },
-	};
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	if (priv->sleeping)
-		return 0;
+	if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
+		*snr = div_s64(c->cnr.stat[0].svalue, 100);
+	else
+		*snr = 0;
 
-	/* reports SNR in resolution of 0.1 dB */
+	return 0;
+}
 
-	ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
-	if (ret)
-		goto err;
+static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 
-	constellation = (tmp >> 2) & 0x03; /* [3:2] */
-	if (constellation > CONSTELLATION_NUM - 1)
-		goto err;
+	*ber = (dev->post_bit_error - dev->post_bit_error_prev);
+	dev->post_bit_error_prev = dev->post_bit_error;
 
-	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
-	if (hierarchy > HIERARCHY_NUM - 1)
-		goto err;
+	return 0;
+}
 
-	ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
-	if (ret)
-		goto err;
+static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
 
-	tmp16 = buf[0] << 8 | buf[1];
+	return 0;
+}
+
+static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	if (tmp16)
-		*snr = (snr_constant[constellation][hierarchy] -
-				intlog10(tmp16)) / ((1 << 24) / 100);
+	if (c->strength.stat[0].scale == FE_SCALE_RELATIVE)
+		*strength = c->strength.stat[0].uvalue;
 	else
-		*snr = 0;
+		*strength = 0;
 
 	return 0;
+}
+
+static struct dvb_frontend_ops rtl2830_ops = {
+	.delsys = {SYS_DVBT},
+	.info = {
+		.name = "Realtek RTL2830 (DVB-T)",
+		.caps = FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+
+	.init = rtl2830_init,
+	.sleep = rtl2830_sleep,
+
+	.get_tune_settings = rtl2830_get_tune_settings,
+
+	.set_frontend = rtl2830_set_frontend,
+	.get_frontend = rtl2830_get_frontend,
+
+	.read_status = rtl2830_read_status,
+	.read_snr = rtl2830_read_snr,
+	.read_ber = rtl2830_read_ber,
+	.read_ucblocks = rtl2830_read_ucblocks,
+	.read_signal_strength = rtl2830_read_signal_strength,
+};
+
+static void rtl2830_stat_work(struct work_struct *work)
+{
+	struct rtl2830_dev *dev = container_of(work, struct rtl2830_dev, stat_work.work);
+	struct i2c_client *client = dev->client;
+	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
+	int ret, tmp;
+	u8 u8tmp, buf[2];
+	u16 u16tmp;
+
+	dev_dbg(&client->dev, "\n");
+
+	/* signal strength */
+	if (dev->fe_status & FE_HAS_SIGNAL) {
+		struct {signed int x:14; } s;
+
+		/* read IF AGC */
+		ret = rtl2830_bulk_read(client, 0x359, buf, 2);
+		if (ret)
+			goto err;
+
+		u16tmp = buf[0] << 8 | buf[1] << 0;
+		u16tmp &= 0x3fff; /* [13:0] */
+		tmp = s.x = u16tmp; /* 14-bit bin to 2 complement */
+		u16tmp = clamp_val(-4 * tmp + 32767, 0x0000, 0xffff);
+
+		dev_dbg(&client->dev, "IF AGC=%d\n", tmp);
+
+		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+		c->strength.stat[0].uvalue = u16tmp;
+	} else {
+		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* CNR */
+	if (dev->fe_status & FE_HAS_VITERBI) {
+		unsigned hierarchy, constellation;
+		#define CONSTELLATION_NUM 3
+		#define HIERARCHY_NUM 4
+		static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
+			{70705899, 70705899, 70705899, 70705899},
+			{82433173, 82433173, 87483115, 94445660},
+			{92888734, 92888734, 95487525, 99770748},
+		};
+
+		ret = rtl2830_bulk_read(client, 0x33c, &u8tmp, 1);
+		if (ret)
+			goto err;
+
+		constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
+		if (constellation > CONSTELLATION_NUM - 1)
+			goto err_schedule_delayed_work;
+
+		hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
+		if (hierarchy > HIERARCHY_NUM - 1)
+			goto err_schedule_delayed_work;
+
+		ret = rtl2830_bulk_read(client, 0x40c, buf, 2);
+		if (ret)
+			goto err;
+
+		u16tmp = buf[0] << 8 | buf[1] << 0;
+		if (u16tmp)
+			tmp = (constant[constellation][hierarchy] -
+			       intlog10(u16tmp)) / ((1 << 24) / 10000);
+		else
+			tmp = 0;
+
+		dev_dbg(&client->dev, "CNR raw=%u\n", u16tmp);
+
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+		c->cnr.stat[0].svalue = tmp;
+	} else {
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* BER */
+	if (dev->fe_status & FE_HAS_LOCK) {
+		ret = rtl2830_bulk_read(client, 0x34e, buf, 2);
+		if (ret)
+			goto err;
+
+		u16tmp = buf[0] << 8 | buf[1] << 0;
+		dev->post_bit_error += u16tmp;
+		dev->post_bit_count += 1000000;
+
+		dev_dbg(&client->dev, "BER errors=%u total=1000000\n", u16tmp);
+
+		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
+		c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
+	} else {
+		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+err_schedule_delayed_work:
+	schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
+	return;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 }
 
-static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
+static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
 	int ret;
-	u8 buf[2];
+	u8 u8tmp;
 
-	if (priv->sleeping)
-		return 0;
+	dev_dbg(&client->dev, "onoff=%d\n", onoff);
+
+	/* enable / disable PID filter */
+	if (onoff)
+		u8tmp = 0x80;
+	else
+		u8tmp = 0x00;
 
-	ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
+	ret = rtl2830_update_bits(client, 0x061, 0x80, u8tmp);
 	if (ret)
 		goto err;
 
-	*ber = buf[0] << 8 | buf[1];
-
 	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int onoff)
 {
-	*ucblocks = 0;
-	return 0;
-}
-
-static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	u8 buf[2];
-	u16 if_agc_raw, if_agc;
+	u8 buf[4];
 
-	if (priv->sleeping)
+	dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n",
+		index, pid, onoff);
+
+	/* skip invalid PIDs (0x2000) */
+	if (pid > 0x1fff || index > 32)
 		return 0;
 
-	ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
+	if (onoff)
+		set_bit(index, &dev->filters);
+	else
+		clear_bit(index, &dev->filters);
+
+	/* enable / disable PIDs */
+	buf[0] = (dev->filters >>  0) & 0xff;
+	buf[1] = (dev->filters >>  8) & 0xff;
+	buf[2] = (dev->filters >> 16) & 0xff;
+	buf[3] = (dev->filters >> 24) & 0xff;
+	ret = rtl2830_bulk_write(client, 0x062, buf, 4);
 	if (ret)
 		goto err;
 
-	if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
-
-	if (if_agc_raw & (1 << 9))
-		if_agc = -(~(if_agc_raw - 1) & 0x1ff);
-	else
-		if_agc = if_agc_raw;
-
-	*strength = (u8) (55 - if_agc / 182);
-	*strength |= *strength << 8;
+	/* add PID */
+	buf[0] = (pid >> 8) & 0xff;
+	buf[1] = (pid >> 0) & 0xff;
+	ret = rtl2830_bulk_write(client, 0x066 + 2 * index, buf, 2);
+	if (ret)
+		goto err;
 
 	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static struct dvb_frontend_ops rtl2830_ops;
-
-static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
-	struct i2c_msg msg[], int num)
+/*
+ * I2C gate/mux/repeater logic
+ * We must use unlocked __i2c_transfer() here (through regmap) because of I2C
+ * adapter lock is already taken by tuner driver.
+ * Gate is closed automatically after single I2C transfer.
+ */
+static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
 {
-	struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
+	struct i2c_client *client = mux_priv;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 	int ret;
 
-	/* open i2c-gate */
-	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
+	dev_dbg(&client->dev, "\n");
+
+	/* open I2C repeater for 1 transfer, closes automatically */
+	/* XXX: regmap_update_bits() does not lock I2C adapter */
+	ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
 	if (ret)
 		goto err;
 
-	ret = i2c_transfer(priv->i2c, msg, num);
-	if (ret < 0)
-		dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n",
-			KBUILD_MODNAME, ret);
-
-	return ret;
+	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
-	.master_xfer   = rtl2830_tuner_i2c_xfer,
-	.functionality = rtl2830_tuner_i2c_func,
-};
+static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client)
+{
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 
-struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+	dev_dbg(&client->dev, "\n");
+
+	return &dev->fe;
+}
+
+static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	return &priv->tuner_i2c_adapter;
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "\n");
+
+	return dev->adapter;
 }
-EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
 
-static void rtl2830_release(struct dvb_frontend *fe)
+/*
+ * We implement own I2C access routines for regmap in order to get manual access
+ * to I2C adapter lock, which is needed for I2C mux adapter.
+ */
+static int rtl2830_regmap_read(void *context, const void *reg_buf,
+			       size_t reg_size, void *val_buf, size_t val_size)
 {
-	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct i2c_client *client = context;
+	int ret;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = reg_size,
+			.buf = (u8 *)reg_buf,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = val_size,
+			.buf = val_buf,
+		}
+	};
 
-	i2c_del_adapter(&priv->tuner_i2c_adapter);
-	kfree(priv);
+	ret = __i2c_transfer(client->adapter, msg, 2);
+	if (ret != 2) {
+		dev_warn(&client->dev, "i2c reg read failed %d\n", ret);
+		if (ret >= 0)
+			ret = -EREMOTEIO;
+		return ret;
+	}
+	return 0;
 }
 
-struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
-	struct i2c_adapter *i2c)
+static int rtl2830_regmap_write(void *context, const void *data, size_t count)
 {
-	struct rtl2830_priv *priv = NULL;
-	int ret = 0;
-	u8 tmp;
+	struct i2c_client *client = context;
+	int ret;
+	struct i2c_msg msg[1] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = count,
+			.buf = (u8 *)data,
+		}
+	};
+
+	ret = __i2c_transfer(client->adapter, msg, 1);
+	if (ret != 1) {
+		dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
+		if (ret >= 0)
+			ret = -EREMOTEIO;
+		return ret;
+	}
+	return 0;
+}
+
+static int rtl2830_regmap_gather_write(void *context, const void *reg,
+				       size_t reg_len, const void *val,
+				       size_t val_len)
+{
+	struct i2c_client *client = context;
+	int ret;
+	u8 buf[256];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1 + val_len,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = *(u8 const *)reg;
+	memcpy(&buf[1], val, val_len);
+
+	ret = __i2c_transfer(client->adapter, msg, 1);
+	if (ret != 1) {
+		dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
+		if (ret >= 0)
+			ret = -EREMOTEIO;
+		return ret;
+	}
+	return 0;
+}
+
+static int rtl2830_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct rtl2830_platform_data *pdata = client->dev.platform_data;
+	struct rtl2830_dev *dev;
+	int ret;
+	u8 u8tmp;
+	static const struct regmap_bus regmap_bus = {
+		.read = rtl2830_regmap_read,
+		.write = rtl2830_regmap_write,
+		.gather_write = rtl2830_regmap_gather_write,
+		.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	};
+	static const struct regmap_range_cfg regmap_range_cfg[] = {
+		{
+			.selector_reg     = 0x00,
+			.selector_mask    = 0xff,
+			.selector_shift   = 0,
+			.window_start     = 0,
+			.window_len       = 0x100,
+			.range_min        = 0 * 0x100,
+			.range_max        = 5 * 0x100,
+		},
+	};
+	static const struct regmap_config regmap_config = {
+		.reg_bits    =  8,
+		.val_bits    =  8,
+		.max_register = 5 * 0x100,
+		.ranges = regmap_range_cfg,
+		.num_ranges = ARRAY_SIZE(regmap_range_cfg),
+	};
+
+	dev_dbg(&client->dev, "\n");
+
+	if (pdata == NULL) {
+		ret = -EINVAL;
+		goto err;
+	}
 
 	/* allocate memory for the internal state */
-	priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
-	if (priv == NULL)
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		ret = -ENOMEM;
 		goto err;
+	}
 
-	/* setup the priv */
-	priv->i2c = i2c;
-	memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
+	/* setup the state */
+	i2c_set_clientdata(client, dev);
+	dev->client = client;
+	dev->pdata = client->dev.platform_data;
+	dev->sleeping = true;
+	INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work);
+	dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
+				  &regmap_config);
+	if (IS_ERR(dev->regmap)) {
+		ret = PTR_ERR(dev->regmap);
+		goto err_kfree;
+	}
 
 	/* check if the demod is there */
-	ret = rtl2830_rd_reg(priv, 0x000, &tmp);
+	ret = rtl2830_bulk_read(client, 0x000, &u8tmp, 1);
 	if (ret)
-		goto err;
-
-	/* create dvb_frontend */
-	memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-
-	/* create tuner i2c adapter */
-	strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
-		sizeof(priv->tuner_i2c_adapter.name));
-	priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
-	priv->tuner_i2c_adapter.algo_data = NULL;
-	priv->tuner_i2c_adapter.dev.parent = &i2c->dev;
-	i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
-	if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
-		dev_err(&i2c->dev,
-				"%s: tuner i2c bus could not be initialized\n",
-				KBUILD_MODNAME);
-		goto err;
+		goto err_regmap_exit;
+
+	/* create muxed i2c adapter for tuner */
+	dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
+			client, 0, 0, 0, rtl2830_select, NULL);
+	if (dev->adapter == NULL) {
+		ret = -ENODEV;
+		goto err_regmap_exit;
 	}
 
-	priv->sleeping = true;
+	/* create dvb frontend */
+	memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops));
+	dev->fe.demodulator_priv = client;
+
+	/* setup callbacks */
+	pdata->get_dvb_frontend = rtl2830_get_dvb_frontend;
+	pdata->get_i2c_adapter = rtl2830_get_i2c_adapter;
+	pdata->pid_filter = rtl2830_pid_filter;
+	pdata->pid_filter_ctrl = rtl2830_pid_filter_ctrl;
 
-	return &priv->fe;
+	dev_info(&client->dev, "Realtek RTL2830 successfully attached\n");
+
+	return 0;
+err_regmap_exit:
+	regmap_exit(dev->regmap);
+err_kfree:
+	kfree(dev);
 err:
-	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
-	kfree(priv);
-	return NULL;
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
 }
-EXPORT_SYMBOL(rtl2830_attach);
 
-static struct dvb_frontend_ops rtl2830_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Realtek RTL2830 (DVB-T)",
-		.caps = FE_CAN_FEC_1_2 |
-			FE_CAN_FEC_2_3 |
-			FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 |
-			FE_CAN_FEC_7_8 |
-			FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
+static int rtl2830_remove(struct i2c_client *client)
+{
+	struct rtl2830_dev *dev = i2c_get_clientdata(client);
 
-	.release = rtl2830_release,
+	dev_dbg(&client->dev, "\n");
 
-	.init = rtl2830_init,
-	.sleep = rtl2830_sleep,
+	i2c_del_mux_adapter(dev->adapter);
+	regmap_exit(dev->regmap);
+	kfree(dev);
 
-	.get_tune_settings = rtl2830_get_tune_settings,
+	return 0;
+}
 
-	.set_frontend = rtl2830_set_frontend,
-	.get_frontend = rtl2830_get_frontend,
+static const struct i2c_device_id rtl2830_id_table[] = {
+	{"rtl2830", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, rtl2830_id_table);
 
-	.read_status = rtl2830_read_status,
-	.read_snr = rtl2830_read_snr,
-	.read_ber = rtl2830_read_ber,
-	.read_ucblocks = rtl2830_read_ucblocks,
-	.read_signal_strength = rtl2830_read_signal_strength,
+static struct i2c_driver rtl2830_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "rtl2830",
+	},
+	.probe		= rtl2830_probe,
+	.remove		= rtl2830_remove,
+	.id_table	= rtl2830_id_table,
 };
 
+module_i2c_driver(rtl2830_driver);
+
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h
index 3313847fb0be..0cde151e6608 100644
--- a/drivers/media/dvb-frontends/rtl2830.h
+++ b/drivers/media/dvb-frontends/rtl2830.h
@@ -13,78 +13,37 @@
  *    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 RTL2830_H
 #define RTL2830_H
 
-#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
-struct rtl2830_config {
-	/*
-	 * Demodulator I2C address.
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * Xtal frequency.
-	 * Hz
-	 * 4000000, 16000000, 25000000, 28800000
-	 */
-	u32 xtal;
-
-	/*
-	 * TS output mode.
-	 */
-	u8 ts_mode;
+/**
+ * struct rtl2830_platform_data - Platform data for the rtl2830 driver
+ * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
+ * @spec_inv: Spectrum inversion.
+ * @vtop: AGC take-over point.
+ * @krf: AGC ratio.
+ * @agc_targ_val: AGC.
+ * @get_dvb_frontend: Get DVB frontend.
+ * @get_i2c_adapter: Get I2C adapter.
+ * @pid_filter: Set PID to PID filter.
+ * @pid_filter_ctrl: Control PID filter.
+ */
 
-	/*
-	 * Spectrum inversion.
-	 */
+struct rtl2830_platform_data {
+	u32 clk;
 	bool spec_inv;
-
-	/*
-	 */
 	u8 vtop;
-
-	/*
-	 */
 	u8 krf;
-
-	/*
-	 */
 	u8 agc_targ_val;
-};
-
-#if IS_ENABLED(CONFIG_DVB_RTL2830)
-extern struct dvb_frontend *rtl2830_attach(
-	const struct rtl2830_config *config,
-	struct i2c_adapter *i2c
-);
 
-extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-);
-#else
-static inline struct dvb_frontend *rtl2830_attach(
-	const struct rtl2830_config *config,
-	struct i2c_adapter *i2c
-)
-{
-	pr_warn("%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-)
-{
-	return NULL;
-}
-#endif
+	struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
+	struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
+	int (*pid_filter)(struct dvb_frontend *, u8, u16, int);
+	int (*pid_filter_ctrl)(struct dvb_frontend *, int);
+};
 
 #endif /* RTL2830_H */
diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h
index fab10ecb3c3b..d50d5376c9c5 100644
--- a/drivers/media/dvb-frontends/rtl2830_priv.h
+++ b/drivers/media/dvb-frontends/rtl2830_priv.h
@@ -13,9 +13,6 @@
  *    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 RTL2830_PRIV_H
@@ -24,16 +21,23 @@
 #include "dvb_frontend.h"
 #include "dvb_math.h"
 #include "rtl2830.h"
+#include <linux/i2c-mux.h>
+#include <linux/math64.h>
+#include <linux/regmap.h>
 
-struct rtl2830_priv {
-	struct i2c_adapter *i2c;
+struct rtl2830_dev {
+	struct rtl2830_platform_data *pdata;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct i2c_adapter *adapter;
 	struct dvb_frontend fe;
-	struct rtl2830_config cfg;
-	struct i2c_adapter tuner_i2c_adapter;
-
 	bool sleeping;
-
-	u8 page; /* active register page */
+	unsigned long filters;
+	struct delayed_work stat_work;
+	fe_status_t fe_status;
+	u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
+	u64 post_bit_error;
+	u64 post_bit_count;
 };
 
 struct rtl2830_reg_val_mask {
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 9026e1aee163..5d2d8f45b4b6 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -2,6 +2,7 @@
  * Realtek RTL2832 DVB-T demodulator driver
  *
  * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
+ * Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi>
  *
  *	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
@@ -19,280 +20,191 @@
  */
 
 #include "rtl2832_priv.h"
-#include "dvb_math.h"
-#include <linux/bitops.h>
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
 #define REG_MASK(b) (BIT(b + 1) - 1)
 
 static const struct rtl2832_reg_entry registers[] = {
-	[DVBT_SOFT_RST]		= {0x1, 0x1,   2, 2},
-	[DVBT_IIC_REPEAT]	= {0x1, 0x1,   3, 3},
-	[DVBT_TR_WAIT_MIN_8K]	= {0x1, 0x88, 11, 2},
-	[DVBT_RSD_BER_FAIL_VAL]	= {0x1, 0x8f, 15, 0},
-	[DVBT_EN_BK_TRK]	= {0x1, 0xa6,  7, 7},
-	[DVBT_AD_EN_REG]	= {0x0, 0x8,   7, 7},
-	[DVBT_AD_EN_REG1]	= {0x0, 0x8,   6, 6},
-	[DVBT_EN_BBIN]		= {0x1, 0xb1,  0, 0},
-	[DVBT_MGD_THD0]		= {0x1, 0x95,  7, 0},
-	[DVBT_MGD_THD1]		= {0x1, 0x96,  7, 0},
-	[DVBT_MGD_THD2]		= {0x1, 0x97,  7, 0},
-	[DVBT_MGD_THD3]		= {0x1, 0x98,  7, 0},
-	[DVBT_MGD_THD4]		= {0x1, 0x99,  7, 0},
-	[DVBT_MGD_THD5]		= {0x1, 0x9a,  7, 0},
-	[DVBT_MGD_THD6]		= {0x1, 0x9b,  7, 0},
-	[DVBT_MGD_THD7]		= {0x1, 0x9c,  7, 0},
-	[DVBT_EN_CACQ_NOTCH]	= {0x1, 0x61,  4, 4},
-	[DVBT_AD_AV_REF]	= {0x0, 0x9,   6, 0},
-	[DVBT_REG_PI]		= {0x0, 0xa,   2, 0},
-	[DVBT_PIP_ON]		= {0x0, 0x21,  3, 3},
-	[DVBT_SCALE1_B92]	= {0x2, 0x92,  7, 0},
-	[DVBT_SCALE1_B93]	= {0x2, 0x93,  7, 0},
-	[DVBT_SCALE1_BA7]	= {0x2, 0xa7,  7, 0},
-	[DVBT_SCALE1_BA9]	= {0x2, 0xa9,  7, 0},
-	[DVBT_SCALE1_BAA]	= {0x2, 0xaa,  7, 0},
-	[DVBT_SCALE1_BAB]	= {0x2, 0xab,  7, 0},
-	[DVBT_SCALE1_BAC]	= {0x2, 0xac,  7, 0},
-	[DVBT_SCALE1_BB0]	= {0x2, 0xb0,  7, 0},
-	[DVBT_SCALE1_BB1]	= {0x2, 0xb1,  7, 0},
-	[DVBT_KB_P1]		= {0x1, 0x64,  3, 1},
-	[DVBT_KB_P2]		= {0x1, 0x64,  6, 4},
-	[DVBT_KB_P3]		= {0x1, 0x65,  2, 0},
-	[DVBT_OPT_ADC_IQ]	= {0x0, 0x6,   5, 4},
-	[DVBT_AD_AVI]		= {0x0, 0x9,   1, 0},
-	[DVBT_AD_AVQ]		= {0x0, 0x9,   3, 2},
-	[DVBT_K1_CR_STEP12]	= {0x2, 0xad,  9, 4},
-	[DVBT_TRK_KS_P2]	= {0x1, 0x6f,  2, 0},
-	[DVBT_TRK_KS_I2]	= {0x1, 0x70,  5, 3},
-	[DVBT_TR_THD_SET2]	= {0x1, 0x72,  3, 0},
-	[DVBT_TRK_KC_P2]	= {0x1, 0x73,  5, 3},
-	[DVBT_TRK_KC_I2]	= {0x1, 0x75,  2, 0},
-	[DVBT_CR_THD_SET2]	= {0x1, 0x76,  7, 6},
-	[DVBT_PSET_IFFREQ]	= {0x1, 0x19, 21, 0},
-	[DVBT_SPEC_INV]		= {0x1, 0x15,  0, 0},
-	[DVBT_RSAMP_RATIO]	= {0x1, 0x9f, 27, 2},
-	[DVBT_CFREQ_OFF_RATIO]	= {0x1, 0x9d, 23, 4},
-	[DVBT_FSM_STAGE]	= {0x3, 0x51,  6, 3},
-	[DVBT_RX_CONSTEL]	= {0x3, 0x3c,  3, 2},
-	[DVBT_RX_HIER]		= {0x3, 0x3c,  6, 4},
-	[DVBT_RX_C_RATE_LP]	= {0x3, 0x3d,  2, 0},
-	[DVBT_RX_C_RATE_HP]	= {0x3, 0x3d,  5, 3},
-	[DVBT_GI_IDX]		= {0x3, 0x51,  1, 0},
-	[DVBT_FFT_MODE_IDX]	= {0x3, 0x51,  2, 2},
-	[DVBT_RSD_BER_EST]	= {0x3, 0x4e, 15, 0},
-	[DVBT_CE_EST_EVM]	= {0x4, 0xc,  15, 0},
-	[DVBT_RF_AGC_VAL]	= {0x3, 0x5b, 13, 0},
-	[DVBT_IF_AGC_VAL]	= {0x3, 0x59, 13, 0},
-	[DVBT_DAGC_VAL]		= {0x3, 0x5,   7, 0},
-	[DVBT_SFREQ_OFF]	= {0x3, 0x18, 13, 0},
-	[DVBT_CFREQ_OFF]	= {0x3, 0x5f, 17, 0},
-	[DVBT_POLAR_RF_AGC]	= {0x0, 0xe,   1, 1},
-	[DVBT_POLAR_IF_AGC]	= {0x0, 0xe,   0, 0},
-	[DVBT_AAGC_HOLD]	= {0x1, 0x4,   5, 5},
-	[DVBT_EN_RF_AGC]	= {0x1, 0x4,   6, 6},
-	[DVBT_EN_IF_AGC]	= {0x1, 0x4,   7, 7},
-	[DVBT_IF_AGC_MIN]	= {0x1, 0x8,   7, 0},
-	[DVBT_IF_AGC_MAX]	= {0x1, 0x9,   7, 0},
-	[DVBT_RF_AGC_MIN]	= {0x1, 0xa,   7, 0},
-	[DVBT_RF_AGC_MAX]	= {0x1, 0xb,   7, 0},
-	[DVBT_IF_AGC_MAN]	= {0x1, 0xc,   6, 6},
-	[DVBT_IF_AGC_MAN_VAL]	= {0x1, 0xc,  13, 0},
-	[DVBT_RF_AGC_MAN]	= {0x1, 0xe,   6, 6},
-	[DVBT_RF_AGC_MAN_VAL]	= {0x1, 0xe,  13, 0},
-	[DVBT_DAGC_TRG_VAL]	= {0x1, 0x12,  7, 0},
-	[DVBT_AGC_TARG_VAL_0]	= {0x1, 0x2,   0, 0},
-	[DVBT_AGC_TARG_VAL_8_1]	= {0x1, 0x3,   7, 0},
-	[DVBT_AAGC_LOOP_GAIN]	= {0x1, 0xc7,  5, 1},
-	[DVBT_LOOP_GAIN2_3_0]	= {0x1, 0x4,   4, 1},
-	[DVBT_LOOP_GAIN2_4]	= {0x1, 0x5,   7, 7},
-	[DVBT_LOOP_GAIN3]	= {0x1, 0xc8,  4, 0},
-	[DVBT_VTOP1]		= {0x1, 0x6,   5, 0},
-	[DVBT_VTOP2]		= {0x1, 0xc9,  5, 0},
-	[DVBT_VTOP3]		= {0x1, 0xca,  5, 0},
-	[DVBT_KRF1]		= {0x1, 0xcb,  7, 0},
-	[DVBT_KRF2]		= {0x1, 0x7,   7, 0},
-	[DVBT_KRF3]		= {0x1, 0xcd,  7, 0},
-	[DVBT_KRF4]		= {0x1, 0xce,  7, 0},
-	[DVBT_EN_GI_PGA]	= {0x1, 0xe5,  0, 0},
-	[DVBT_THD_LOCK_UP]	= {0x1, 0xd9,  8, 0},
-	[DVBT_THD_LOCK_DW]	= {0x1, 0xdb,  8, 0},
-	[DVBT_THD_UP1]		= {0x1, 0xdd,  7, 0},
-	[DVBT_THD_DW1]		= {0x1, 0xde,  7, 0},
-	[DVBT_INTER_CNT_LEN]	= {0x1, 0xd8,  3, 0},
-	[DVBT_GI_PGA_STATE]	= {0x1, 0xe6,  3, 3},
-	[DVBT_EN_AGC_PGA]	= {0x1, 0xd7,  0, 0},
-	[DVBT_CKOUTPAR]		= {0x1, 0x7b,  5, 5},
-	[DVBT_CKOUT_PWR]	= {0x1, 0x7b,  6, 6},
-	[DVBT_SYNC_DUR]		= {0x1, 0x7b,  7, 7},
-	[DVBT_ERR_DUR]		= {0x1, 0x7c,  0, 0},
-	[DVBT_SYNC_LVL]		= {0x1, 0x7c,  1, 1},
-	[DVBT_ERR_LVL]		= {0x1, 0x7c,  2, 2},
-	[DVBT_VAL_LVL]		= {0x1, 0x7c,  3, 3},
-	[DVBT_SERIAL]		= {0x1, 0x7c,  4, 4},
-	[DVBT_SER_LSB]		= {0x1, 0x7c,  5, 5},
-	[DVBT_CDIV_PH0]		= {0x1, 0x7d,  3, 0},
-	[DVBT_CDIV_PH1]		= {0x1, 0x7d,  7, 4},
-	[DVBT_MPEG_IO_OPT_2_2]	= {0x0, 0x6,   7, 7},
-	[DVBT_MPEG_IO_OPT_1_0]	= {0x0, 0x7,   7, 6},
-	[DVBT_CKOUTPAR_PIP]	= {0x0, 0xb7,  4, 4},
-	[DVBT_CKOUT_PWR_PIP]	= {0x0, 0xb7,  3, 3},
-	[DVBT_SYNC_LVL_PIP]	= {0x0, 0xb7,  2, 2},
-	[DVBT_ERR_LVL_PIP]	= {0x0, 0xb7,  1, 1},
-	[DVBT_VAL_LVL_PIP]	= {0x0, 0xb7,  0, 0},
-	[DVBT_CKOUTPAR_PID]	= {0x0, 0xb9,  4, 4},
-	[DVBT_CKOUT_PWR_PID]	= {0x0, 0xb9,  3, 3},
-	[DVBT_SYNC_LVL_PID]	= {0x0, 0xb9,  2, 2},
-	[DVBT_ERR_LVL_PID]	= {0x0, 0xb9,  1, 1},
-	[DVBT_VAL_LVL_PID]	= {0x0, 0xb9,  0, 0},
-	[DVBT_SM_PASS]		= {0x1, 0x93, 11, 0},
-	[DVBT_AD7_SETTING]	= {0x0, 0x11, 15, 0},
-	[DVBT_RSSI_R]		= {0x3, 0x1,   6, 0},
-	[DVBT_ACI_DET_IND]	= {0x3, 0x12,  0, 0},
-	[DVBT_REG_MON]		= {0x0, 0xd,   1, 0},
-	[DVBT_REG_MONSEL]	= {0x0, 0xd,   2, 2},
-	[DVBT_REG_GPE]		= {0x0, 0xd,   7, 7},
-	[DVBT_REG_GPO]		= {0x0, 0x10,  0, 0},
-	[DVBT_REG_4MSEL]	= {0x0, 0x13,  0, 0},
+	[DVBT_SOFT_RST]		= {0x101,  2, 2},
+	[DVBT_IIC_REPEAT]	= {0x101,  3, 3},
+	[DVBT_TR_WAIT_MIN_8K]	= {0x188, 11, 2},
+	[DVBT_RSD_BER_FAIL_VAL]	= {0x18f, 15, 0},
+	[DVBT_EN_BK_TRK]	= {0x1a6,  7, 7},
+	[DVBT_AD_EN_REG]	= {0x008,  7, 7},
+	[DVBT_AD_EN_REG1]	= {0x008,  6, 6},
+	[DVBT_EN_BBIN]		= {0x1b1,  0, 0},
+	[DVBT_MGD_THD0]		= {0x195,  7, 0},
+	[DVBT_MGD_THD1]		= {0x196,  7, 0},
+	[DVBT_MGD_THD2]		= {0x197,  7, 0},
+	[DVBT_MGD_THD3]		= {0x198,  7, 0},
+	[DVBT_MGD_THD4]		= {0x199,  7, 0},
+	[DVBT_MGD_THD5]		= {0x19a,  7, 0},
+	[DVBT_MGD_THD6]		= {0x19b,  7, 0},
+	[DVBT_MGD_THD7]		= {0x19c,  7, 0},
+	[DVBT_EN_CACQ_NOTCH]	= {0x161,  4, 4},
+	[DVBT_AD_AV_REF]	= {0x009,  6, 0},
+	[DVBT_REG_PI]		= {0x00a,  2, 0},
+	[DVBT_PIP_ON]		= {0x021,  3, 3},
+	[DVBT_SCALE1_B92]	= {0x292,  7, 0},
+	[DVBT_SCALE1_B93]	= {0x293,  7, 0},
+	[DVBT_SCALE1_BA7]	= {0x2a7,  7, 0},
+	[DVBT_SCALE1_BA9]	= {0x2a9,  7, 0},
+	[DVBT_SCALE1_BAA]	= {0x2aa,  7, 0},
+	[DVBT_SCALE1_BAB]	= {0x2ab,  7, 0},
+	[DVBT_SCALE1_BAC]	= {0x2ac,  7, 0},
+	[DVBT_SCALE1_BB0]	= {0x2b0,  7, 0},
+	[DVBT_SCALE1_BB1]	= {0x2b1,  7, 0},
+	[DVBT_KB_P1]		= {0x164,  3, 1},
+	[DVBT_KB_P2]		= {0x164,  6, 4},
+	[DVBT_KB_P3]		= {0x165,  2, 0},
+	[DVBT_OPT_ADC_IQ]	= {0x006,  5, 4},
+	[DVBT_AD_AVI]		= {0x009,  1, 0},
+	[DVBT_AD_AVQ]		= {0x009,  3, 2},
+	[DVBT_K1_CR_STEP12]	= {0x2ad,  9, 4},
+	[DVBT_TRK_KS_P2]	= {0x16f,  2, 0},
+	[DVBT_TRK_KS_I2]	= {0x170,  5, 3},
+	[DVBT_TR_THD_SET2]	= {0x172,  3, 0},
+	[DVBT_TRK_KC_P2]	= {0x173,  5, 3},
+	[DVBT_TRK_KC_I2]	= {0x175,  2, 0},
+	[DVBT_CR_THD_SET2]	= {0x176,  7, 6},
+	[DVBT_PSET_IFFREQ]	= {0x119, 21, 0},
+	[DVBT_SPEC_INV]		= {0x115,  0, 0},
+	[DVBT_RSAMP_RATIO]	= {0x19f, 27, 2},
+	[DVBT_CFREQ_OFF_RATIO]	= {0x19d, 23, 4},
+	[DVBT_FSM_STAGE]	= {0x351,  6, 3},
+	[DVBT_RX_CONSTEL]	= {0x33c,  3, 2},
+	[DVBT_RX_HIER]		= {0x33c,  6, 4},
+	[DVBT_RX_C_RATE_LP]	= {0x33d,  2, 0},
+	[DVBT_RX_C_RATE_HP]	= {0x33d,  5, 3},
+	[DVBT_GI_IDX]		= {0x351,  1, 0},
+	[DVBT_FFT_MODE_IDX]	= {0x351,  2, 2},
+	[DVBT_RSD_BER_EST]	= {0x34e, 15, 0},
+	[DVBT_CE_EST_EVM]	= {0x40c, 15, 0},
+	[DVBT_RF_AGC_VAL]	= {0x35b, 13, 0},
+	[DVBT_IF_AGC_VAL]	= {0x359, 13, 0},
+	[DVBT_DAGC_VAL]		= {0x305,  7, 0},
+	[DVBT_SFREQ_OFF]	= {0x318, 13, 0},
+	[DVBT_CFREQ_OFF]	= {0x35f, 17, 0},
+	[DVBT_POLAR_RF_AGC]	= {0x00e,  1, 1},
+	[DVBT_POLAR_IF_AGC]	= {0x00e,  0, 0},
+	[DVBT_AAGC_HOLD]	= {0x104,  5, 5},
+	[DVBT_EN_RF_AGC]	= {0x104,  6, 6},
+	[DVBT_EN_IF_AGC]	= {0x104,  7, 7},
+	[DVBT_IF_AGC_MIN]	= {0x108,  7, 0},
+	[DVBT_IF_AGC_MAX]	= {0x109,  7, 0},
+	[DVBT_RF_AGC_MIN]	= {0x10a,  7, 0},
+	[DVBT_RF_AGC_MAX]	= {0x10b,  7, 0},
+	[DVBT_IF_AGC_MAN]	= {0x10c,  6, 6},
+	[DVBT_IF_AGC_MAN_VAL]	= {0x10c, 13, 0},
+	[DVBT_RF_AGC_MAN]	= {0x10e,  6, 6},
+	[DVBT_RF_AGC_MAN_VAL]	= {0x10e, 13, 0},
+	[DVBT_DAGC_TRG_VAL]	= {0x112,  7, 0},
+	[DVBT_AGC_TARG_VAL_0]	= {0x102,  0, 0},
+	[DVBT_AGC_TARG_VAL_8_1]	= {0x103,  7, 0},
+	[DVBT_AAGC_LOOP_GAIN]	= {0x1c7,  5, 1},
+	[DVBT_LOOP_GAIN2_3_0]	= {0x104,  4, 1},
+	[DVBT_LOOP_GAIN2_4]	= {0x105,  7, 7},
+	[DVBT_LOOP_GAIN3]	= {0x1c8,  4, 0},
+	[DVBT_VTOP1]		= {0x106,  5, 0},
+	[DVBT_VTOP2]		= {0x1c9,  5, 0},
+	[DVBT_VTOP3]		= {0x1ca,  5, 0},
+	[DVBT_KRF1]		= {0x1cb,  7, 0},
+	[DVBT_KRF2]		= {0x107,  7, 0},
+	[DVBT_KRF3]		= {0x1cd,  7, 0},
+	[DVBT_KRF4]		= {0x1ce,  7, 0},
+	[DVBT_EN_GI_PGA]	= {0x1e5,  0, 0},
+	[DVBT_THD_LOCK_UP]	= {0x1d9,  8, 0},
+	[DVBT_THD_LOCK_DW]	= {0x1db,  8, 0},
+	[DVBT_THD_UP1]		= {0x1dd,  7, 0},
+	[DVBT_THD_DW1]		= {0x1de,  7, 0},
+	[DVBT_INTER_CNT_LEN]	= {0x1d8,  3, 0},
+	[DVBT_GI_PGA_STATE]	= {0x1e6,  3, 3},
+	[DVBT_EN_AGC_PGA]	= {0x1d7,  0, 0},
+	[DVBT_CKOUTPAR]		= {0x17b,  5, 5},
+	[DVBT_CKOUT_PWR]	= {0x17b,  6, 6},
+	[DVBT_SYNC_DUR]		= {0x17b,  7, 7},
+	[DVBT_ERR_DUR]		= {0x17c,  0, 0},
+	[DVBT_SYNC_LVL]		= {0x17c,  1, 1},
+	[DVBT_ERR_LVL]		= {0x17c,  2, 2},
+	[DVBT_VAL_LVL]		= {0x17c,  3, 3},
+	[DVBT_SERIAL]		= {0x17c,  4, 4},
+	[DVBT_SER_LSB]		= {0x17c,  5, 5},
+	[DVBT_CDIV_PH0]		= {0x17d,  3, 0},
+	[DVBT_CDIV_PH1]		= {0x17d,  7, 4},
+	[DVBT_MPEG_IO_OPT_2_2]	= {0x006,  7, 7},
+	[DVBT_MPEG_IO_OPT_1_0]	= {0x007,  7, 6},
+	[DVBT_CKOUTPAR_PIP]	= {0x0b7,  4, 4},
+	[DVBT_CKOUT_PWR_PIP]	= {0x0b7,  3, 3},
+	[DVBT_SYNC_LVL_PIP]	= {0x0b7,  2, 2},
+	[DVBT_ERR_LVL_PIP]	= {0x0b7,  1, 1},
+	[DVBT_VAL_LVL_PIP]	= {0x0b7,  0, 0},
+	[DVBT_CKOUTPAR_PID]	= {0x0b9,  4, 4},
+	[DVBT_CKOUT_PWR_PID]	= {0x0b9,  3, 3},
+	[DVBT_SYNC_LVL_PID]	= {0x0b9,  2, 2},
+	[DVBT_ERR_LVL_PID]	= {0x0b9,  1, 1},
+	[DVBT_VAL_LVL_PID]	= {0x0b9,  0, 0},
+	[DVBT_SM_PASS]		= {0x193, 11, 0},
+	[DVBT_AD7_SETTING]	= {0x011, 15, 0},
+	[DVBT_RSSI_R]		= {0x301,  6, 0},
+	[DVBT_ACI_DET_IND]	= {0x312,  0, 0},
+	[DVBT_REG_MON]		= {0x00d,  1, 0},
+	[DVBT_REG_MONSEL]	= {0x00d,  2, 2},
+	[DVBT_REG_GPE]		= {0x00d,  7, 7},
+	[DVBT_REG_GPO]		= {0x010,  0, 0},
+	[DVBT_REG_4MSEL]	= {0x013,  0, 0},
 };
 
-/* write multiple hardware registers */
-static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
+/* Our regmap is bypassing I2C adapter lock, thus we do it! */
+static int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg,
+			      const void *val, size_t val_count)
 {
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	u8 buf[MAX_XFER_SIZE];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1 + len,
-			.buf = buf,
-		}
-	};
 
-	if (1 + len > sizeof(buf)) {
-		dev_warn(&priv->i2c->dev,
-			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
-			 KBUILD_MODNAME, reg, len);
-		return -EINVAL;
-	}
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->i2c_adapter, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev,
-				"%s: i2c wr failed=%d reg=%02x len=%d\n",
-				KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
+	i2c_lock_adapter(client->adapter);
+	ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
+	i2c_unlock_adapter(client->adapter);
 	return ret;
 }
 
-/* read multiple hardware registers */
-static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
+static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg,
+			       unsigned int mask, unsigned int val)
 {
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
 	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
 
-	ret = i2c_transfer(priv->i2c_adapter, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev,
-				"%s: i2c rd failed=%d reg=%02x len=%d\n",
-				KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
+	i2c_lock_adapter(client->adapter);
+	ret = regmap_update_bits(dev->regmap, reg, mask, val);
+	i2c_unlock_adapter(client->adapter);
 	return ret;
 }
 
-/* write multiple registers */
-static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
-	int len)
-{
-	int ret;
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2832_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-}
-
-return rtl2832_wr(priv, reg, val, len);
-}
-
-/* read multiple registers */
-static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
-	int len)
+static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg,
+			     void *val, size_t val_count)
 {
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
 	int ret;
 
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2832_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-	}
-
-	return rtl2832_rd(priv, reg, val, len);
-}
-
-/* write single register */
-static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
-{
-	return rtl2832_wr_regs(priv, reg, page, &val, 1);
-}
-
-/* read single register */
-static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
-{
-	return rtl2832_rd_regs(priv, reg, page, val, 1);
+	i2c_lock_adapter(client->adapter);
+	ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
+	i2c_unlock_adapter(client->adapter);
+	return ret;
 }
 
-static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
+static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
 {
-	int ret;
-
-	u8 reg_start_addr;
-	u8 msb, lsb;
-	u8 page;
-	u8 reading[4];
-	u32 reading_tmp;
-	int i;
-
-	u8 len;
-	u32 mask;
+	struct i2c_client *client = dev->client;
+	int ret, i;
+	u16 reg_start_addr;
+	u8 msb, lsb, reading[4], len;
+	u32 reading_tmp, mask;
 
 	reg_start_addr = registers[reg].start_address;
 	msb = registers[reg].msb;
 	lsb = registers[reg].lsb;
-	page = registers[reg].page;
-
 	len = (msb >> 3) + 1;
 	mask = REG_MASK(msb - lsb);
 
-	ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
+	ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
 	if (ret)
 		goto err;
 
@@ -302,40 +214,27 @@ static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
 
 	*val = (reading_tmp >> lsb) & mask;
 
-	return ret;
-
+	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
-
 }
 
-static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
+static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val)
 {
+	struct i2c_client *client = dev->client;
 	int ret, i;
-	u8 len;
-	u8 reg_start_addr;
-	u8 msb, lsb;
-	u8 page;
-	u32 mask;
-
-
-	u8 reading[4];
-	u8 writing[4];
-	u32 reading_tmp;
-	u32 writing_tmp;
-
+	u16 reg_start_addr;
+	u8 msb, lsb, reading[4], writing[4], len;
+	u32 reading_tmp, writing_tmp, mask;
 
 	reg_start_addr = registers[reg].start_address;
 	msb = registers[reg].msb;
 	lsb = registers[reg].lsb;
-	page = registers[reg].page;
-
 	len = (msb >> 3) + 1;
 	mask = REG_MASK(msb - lsb);
 
-
-	ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
+	ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
 	if (ret)
 		goto err;
 
@@ -346,49 +245,23 @@ static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
 	writing_tmp = reading_tmp & ~(mask << lsb);
 	writing_tmp |= ((val & mask) << lsb);
 
-
 	for (i = 0; i < len; i++)
 		writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
 
-	ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len);
-	if (ret)
-		goto err;
-
-	return ret;
-
-err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-
-}
-
-static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	int ret;
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-
-	dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable);
-
-	/* gate already open or close */
-	if (priv->i2c_gate_state == enable)
-		return 0;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0));
+	ret = rtl2832_bulk_write(client, reg_start_addr, writing, len);
 	if (ret)
 		goto err;
 
-	priv->i2c_gate_state = enable;
-
-	return ret;
+	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-
 static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
 	int ret;
 	u64 pset_iffreq;
 	u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0);
@@ -397,30 +270,35 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq)
 	* PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
 	*		/ CrystalFreqHz)
 	*/
-
-	pset_iffreq = if_freq % priv->cfg.xtal;
+	pset_iffreq = if_freq % dev->pdata->clk;
 	pset_iffreq *= 0x400000;
-	pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
+	pset_iffreq = div_u64(pset_iffreq, dev->pdata->clk);
 	pset_iffreq = -pset_iffreq;
 	pset_iffreq = pset_iffreq & 0x3fffff;
-	dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n",
-			__func__, if_freq, (unsigned)pset_iffreq);
+	dev_dbg(&client->dev, "if_frequency=%d pset_iffreq=%08x\n",
+		if_freq, (unsigned)pset_iffreq);
 
-	ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_EN_BBIN, en_bbin);
 	if (ret)
-		return ret;
+		goto err;
 
-	ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_PSET_IFFREQ, pset_iffreq);
+	if (ret)
+		goto err;
 
+	return 0;
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2832_init(struct dvb_frontend *fe)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
+	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
 	const struct rtl2832_reg_value *init;
 	int i, ret, len;
-
 	/* initialization values for the demodulator registers */
 	struct rtl2832_reg_value rtl2832_initial_regs[] = {
 		{DVBT_AD_EN_REG,		0x1},
@@ -467,19 +345,19 @@ static int rtl2832_init(struct dvb_frontend *fe)
 		{DVBT_CR_THD_SET2,		0x1},
 	};
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	dev_dbg(&client->dev, "\n");
 
 	for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
-		ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
+		ret = rtl2832_wr_demod_reg(dev, rtl2832_initial_regs[i].reg,
 			rtl2832_initial_regs[i].value);
 		if (ret)
 			goto err;
 	}
 
 	/* load tuner specific settings */
-	dev_dbg(&priv->i2c->dev, "%s: load settings for tuner=%02x\n",
-			__func__, priv->cfg.tuner);
-	switch (priv->cfg.tuner) {
+	dev_dbg(&client->dev, "load settings for tuner=%02x\n",
+		dev->pdata->tuner);
+	switch (dev->pdata->tuner) {
 	case RTL2832_TUNER_FC0012:
 	case RTL2832_TUNER_FC0013:
 		len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
@@ -504,51 +382,60 @@ static int rtl2832_init(struct dvb_frontend *fe)
 	}
 
 	for (i = 0; i < len; i++) {
-		ret = rtl2832_wr_demod_reg(priv, init[i].reg, init[i].value);
+		ret = rtl2832_wr_demod_reg(dev, init[i].reg, init[i].value);
 		if (ret)
 			goto err;
 	}
 
-	/*
-	 * r820t NIM code does a software reset here at the demod -
-	 * may not be needed, as there's already a software reset at
-	 * set_params()
-	 */
-#if 1
-	/* soft reset */
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
-	if (ret)
-		goto err;
-#endif
-
-	priv->sleeping = false;
-
-	return ret;
+	/* init stats here in order signal app which stats are supported */
+	c->strength.len = 1;
+	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->cnr.len = 1;
+	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_error.len = 1;
+	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_count.len = 1;
+	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	/* start statistics polling */
+	schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
+	dev->sleeping = false;
 
+	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2832_sleep(struct dvb_frontend *fe)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
+	int ret;
+
+	dev_dbg(&client->dev, "\n");
+
+	dev->sleeping = true;
+	/* stop statistics polling */
+	cancel_delayed_work_sync(&dev->stat_work);
+	dev->fe_status = 0;
+
+	ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1);
+	if (ret)
+		goto err;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-	priv->sleeping = true;
 	return 0;
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
 }
 
 static int rtl2832_get_tune_settings(struct dvb_frontend *fe,
 	struct dvb_frontend_tune_settings *s)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	dev_dbg(&client->dev, "\n");
 	s->min_delay_ms = 1000;
 	s->step_size = fe->ops.info.frequency_stepsize * 2;
 	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
@@ -557,7 +444,8 @@ static int rtl2832_get_tune_settings(struct dvb_frontend *fe,
 
 static int rtl2832_set_frontend(struct dvb_frontend *fe)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i, j;
 	u64 bw_mode, num, num2;
@@ -588,17 +476,15 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
 		},
 	};
 
-
-	dev_dbg(&priv->i2c->dev,
-			"%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
-			__func__, c->frequency, c->bandwidth_hz, c->inversion);
+	dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
+		c->frequency, c->bandwidth_hz, c->inversion);
 
 	/* program tuner */
 	if (fe->ops.tuner_ops.set_params)
 		fe->ops.tuner_ops.set_params(fe);
 
 	/* PIP mode related */
-	ret = rtl2832_wr_regs(priv, 0x92, 1, "\x00\x0f\xff", 3);
+	ret = rtl2832_bulk_write(client, 0x192, "\x00\x0f\xff", 3);
 	if (ret)
 		goto err;
 
@@ -629,12 +515,14 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
 		bw_mode = 64000000;
 		break;
 	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
-		return -EINVAL;
+		dev_err(&client->dev, "invalid bandwidth_hz %u\n",
+			c->bandwidth_hz);
+		ret = -EINVAL;
+		goto err;
 	}
 
 	for (j = 0; j < sizeof(bw_params[0]); j++) {
-		ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1);
+		ret = rtl2832_bulk_write(client, 0x11c + j, &bw_params[i][j], 1);
 		if (ret)
 			goto err;
 	}
@@ -643,11 +531,11 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
 	* RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22)
 	*	/ ConstWithBandwidthMode)
 	*/
-	num = priv->cfg.xtal * 7;
+	num = dev->pdata->clk * 7;
 	num *= 0x400000;
 	num = div_u64(num, bw_mode);
 	resamp_ratio =  num & 0x3ffffff;
-	ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_RSAMP_RATIO, resamp_ratio);
 	if (ret)
 		goto err;
 
@@ -656,48 +544,49 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
 	*	/ (CrystalFreqHz * 7))
 	*/
 	num = bw_mode << 20;
-	num2 = priv->cfg.xtal * 7;
+	num2 = dev->pdata->clk * 7;
 	num = div_u64(num, num2);
 	num = -num;
 	cfreq_off_ratio = num & 0xfffff;
-	ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
 	if (ret)
 		goto err;
 
 	/* soft reset */
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0);
 	if (ret)
 		goto err;
 
-	return ret;
+	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2832_get_frontend(struct dvb_frontend *fe)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 	u8 buf[3];
 
-	if (priv->sleeping)
+	if (dev->sleeping)
 		return 0;
 
-	ret = rtl2832_rd_regs(priv, 0x3c, 3, buf, 2);
+	ret = rtl2832_bulk_read(client, 0x33c, buf, 2);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_rd_reg(priv, 0x51, 3, &buf[2]);
+	ret = rtl2832_bulk_read(client, 0x351, &buf[2], 1);
 	if (ret)
 		goto err;
 
-	dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
+	dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
 
 	switch ((buf[0] >> 2) & 3) {
 	case 0:
@@ -787,403 +676,652 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe)
 
 	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
 	int ret;
 	u32 tmp;
-	*status = 0;
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-	if (priv->sleeping)
+	dev_dbg(&client->dev, "\n");
+
+	*status = 0;
+	if (dev->sleeping)
 		return 0;
 
-	ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp);
+	ret = rtl2832_rd_demod_reg(dev, DVBT_FSM_STAGE, &tmp);
 	if (ret)
 		goto err;
 
 	if (tmp == 11) {
 		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	}
-	/* TODO find out if this is also true for rtl2832? */
-	/*else if (tmp == 10) {
+	} else if (tmp == 10) {
 		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 				FE_HAS_VITERBI;
-	}*/
+	}
 
-	return ret;
+	dev->fe_status = *status;
+	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	int ret, hierarchy, constellation;
-	u8 buf[2], tmp;
-	u16 tmp16;
-#define CONSTELLATION_NUM 3
-#define HIERARCHY_NUM 4
-	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
-		{ 85387325, 85387325, 85387325, 85387325 },
-		{ 86676178, 86676178, 87167949, 87795660 },
-		{ 87659938, 87659938, 87885178, 88241743 },
-	};
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	/* reports SNR in resolution of 0.1 dB */
+	/* report SNR in resolution of 0.1 dB */
+	if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
+		*snr = div_s64(c->cnr.stat[0].svalue, 100);
+	else
+		*snr = 0;
 
-	ret = rtl2832_rd_reg(priv, 0x3c, 3, &tmp);
-	if (ret)
-		goto err;
+	return 0;
+}
 
-	constellation = (tmp >> 2) & 0x03; /* [3:2] */
-	if (constellation > CONSTELLATION_NUM - 1)
-		goto err;
+static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct rtl2832_dev *dev = fe->demodulator_priv;
 
-	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
-	if (hierarchy > HIERARCHY_NUM - 1)
-		goto err;
+	*ber = (dev->post_bit_error - dev->post_bit_error_prev);
+	dev->post_bit_error_prev = dev->post_bit_error;
 
-	ret = rtl2832_rd_regs(priv, 0x0c, 4, buf, 2);
-	if (ret)
-		goto err;
+	return 0;
+}
 
-	tmp16 = buf[0] << 8 | buf[1];
+static void rtl2832_stat_work(struct work_struct *work)
+{
+	struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, stat_work.work);
+	struct i2c_client *client = dev->client;
+	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
+	int ret, tmp;
+	u8 u8tmp, buf[2];
+	u16 u16tmp;
+
+	dev_dbg(&client->dev, "\n");
+
+	/* signal strength */
+	if (dev->fe_status & FE_HAS_SIGNAL) {
+		/* read digital AGC */
+		ret = rtl2832_bulk_read(client, 0x305, &u8tmp, 1);
+		if (ret)
+			goto err;
 
-	if (tmp16)
-		*snr = (snr_constant[constellation][hierarchy] -
-				intlog10(tmp16)) / ((1 << 24) / 100);
-	else
-		*snr = 0;
+		dev_dbg(&client->dev, "digital agc=%02x", u8tmp);
 
-	return 0;
+		u8tmp = ~u8tmp;
+		u16tmp = u8tmp << 8 | u8tmp << 0;
+
+		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+		c->strength.stat[0].uvalue = u16tmp;
+	} else {
+		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* CNR */
+	if (dev->fe_status & FE_HAS_VITERBI) {
+		unsigned hierarchy, constellation;
+		#define CONSTELLATION_NUM 3
+		#define HIERARCHY_NUM 4
+		static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
+			{85387325, 85387325, 85387325, 85387325},
+			{86676178, 86676178, 87167949, 87795660},
+			{87659938, 87659938, 87885178, 88241743},
+		};
+
+		ret = rtl2832_bulk_read(client, 0x33c, &u8tmp, 1);
+		if (ret)
+			goto err;
+
+		constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
+		if (constellation > CONSTELLATION_NUM - 1)
+			goto err_schedule_delayed_work;
+
+		hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
+		if (hierarchy > HIERARCHY_NUM - 1)
+			goto err_schedule_delayed_work;
+
+		ret = rtl2832_bulk_read(client, 0x40c, buf, 2);
+		if (ret)
+			goto err;
+
+		u16tmp = buf[0] << 8 | buf[1] << 0;
+		if (u16tmp)
+			tmp = (constant[constellation][hierarchy] -
+			       intlog10(u16tmp)) / ((1 << 24) / 10000);
+		else
+			tmp = 0;
+
+		dev_dbg(&client->dev, "cnr raw=%u\n", u16tmp);
+
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+		c->cnr.stat[0].svalue = tmp;
+	} else {
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* BER */
+	if (dev->fe_status & FE_HAS_LOCK) {
+		ret = rtl2832_bulk_read(client, 0x34e, buf, 2);
+		if (ret)
+			goto err;
+
+		u16tmp = buf[0] << 8 | buf[1] << 0;
+		dev->post_bit_error += u16tmp;
+		dev->post_bit_count += 1000000;
+
+		dev_dbg(&client->dev, "ber errors=%u total=1000000\n", u16tmp);
+
+		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
+		c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
+	} else {
+		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+err_schedule_delayed_work:
+	schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
+	return;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 }
 
-static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
+/*
+ * I2C gate/mux/repeater logic
+ * We must use unlocked __i2c_transfer() here (through regmap) because of I2C
+ * adapter lock is already taken by tuner driver.
+ * There is delay mechanism to avoid unneeded I2C gate open / close. Gate close
+ * is delayed here a little bit in order to see if there is sequence of I2C
+ * messages sent to same I2C bus.
+ */
+static void rtl2832_i2c_gate_work(struct work_struct *work)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, i2c_gate_work.work);
+	struct i2c_client *client = dev->client;
 	int ret;
-	u8 buf[2];
 
-	ret = rtl2832_rd_regs(priv, 0x4e, 3, buf, 2);
+	/* close gate */
+	ret = rtl2832_update_bits(dev->client, 0x101, 0x08, 0x00);
 	if (ret)
 		goto err;
 
-	*ber = buf[0] << 8 | buf[1];
+	return;
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+}
+
+static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
+{
+	struct rtl2832_dev *dev = mux_priv;
+	struct i2c_client *client = dev->client;
+	int ret;
+
+	/* terminate possible gate closing */
+	cancel_delayed_work(&dev->i2c_gate_work);
+
+	/*
+	 * I2C adapter lock is already taken and due to that we will use
+	 * regmap_update_bits() which does not lock again I2C adapter.
+	 */
+	ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
+	if (ret)
+		goto err;
 
 	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static struct dvb_frontend_ops rtl2832_ops;
+static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
+			    u32 chan_id)
+{
+	struct rtl2832_dev *dev = mux_priv;
+
+	schedule_delayed_work(&dev->i2c_gate_work, usecs_to_jiffies(100));
+	return 0;
+}
+
+static struct dvb_frontend_ops rtl2832_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Realtek RTL2832 (DVB-T)",
+		.frequency_min	  = 174000000,
+		.frequency_max	  = 862000000,
+		.frequency_stepsize = 166667,
+		.caps = FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	 },
 
-static void rtl2832_release(struct dvb_frontend *fe)
+	.init = rtl2832_init,
+	.sleep = rtl2832_sleep,
+
+	.get_tune_settings = rtl2832_get_tune_settings,
+
+	.set_frontend = rtl2832_set_frontend,
+	.get_frontend = rtl2832_get_frontend,
+
+	.read_status = rtl2832_read_status,
+	.read_snr = rtl2832_read_snr,
+	.read_ber = rtl2832_read_ber,
+};
+
+static bool rtl2832_volatile_reg(struct device *dev, unsigned int reg)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	switch (reg) {
+	case 0x305:
+	case 0x33c:
+	case 0x34e:
+	case 0x351:
+	case 0x40c ... 0x40d:
+		return true;
+	default:
+		break;
+	}
 
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-	cancel_delayed_work_sync(&priv->i2c_gate_work);
-	i2c_del_mux_adapter(priv->i2c_adapter_tuner);
-	i2c_del_mux_adapter(priv->i2c_adapter);
-	kfree(priv);
+	return false;
 }
 
 /*
- * Delay mechanism to avoid unneeded I2C gate open / close. Gate close is
- * delayed here a little bit in order to see if there is sequence of I2C
- * messages sent to same I2C bus.
- * We must use unlocked version of __i2c_transfer() in order to avoid deadlock
- * as lock is already taken by calling muxed i2c_transfer().
+ * We implement own I2C access routines for regmap in order to get manual access
+ * to I2C adapter lock, which is needed for I2C mux adapter.
  */
-static void rtl2832_i2c_gate_work(struct work_struct *work)
+static int rtl2832_regmap_read(void *context, const void *reg_buf,
+			       size_t reg_size, void *val_buf, size_t val_size)
 {
-	struct rtl2832_priv *priv = container_of(work,
-			struct rtl2832_priv, i2c_gate_work.work);
-	struct i2c_adapter *adap = priv->i2c;
+	struct i2c_client *client = context;
 	int ret;
-	u8 buf[2];
-	struct i2c_msg msg[1] = {
+	struct i2c_msg msg[2] = {
 		{
-			.addr = priv->cfg.i2c_addr,
+			.addr = client->addr,
 			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
+			.len = reg_size,
+			.buf = (u8 *)reg_buf,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = val_size,
+			.buf = val_buf,
 		}
 	};
 
-	/* select reg bank 1 */
-	buf[0] = 0x00;
-	buf[1] = 0x01;
-	ret = __i2c_transfer(adap, msg, 1);
-	if (ret != 1)
-		goto err;
-
-	priv->page = 1;
-
-	/* close I2C repeater gate */
-	buf[0] = 0x01;
-	buf[1] = 0x10;
-	ret = __i2c_transfer(adap, msg, 1);
-	if (ret != 1)
-		goto err;
-
-	priv->i2c_gate_state = false;
-
-	return;
-err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-
-	return;
+	ret = __i2c_transfer(client->adapter, msg, 2);
+	if (ret != 2) {
+		dev_warn(&client->dev, "i2c reg read failed %d\n", ret);
+		if (ret >= 0)
+			ret = -EREMOTEIO;
+		return ret;
+	}
+	return 0;
 }
 
-static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
+static int rtl2832_regmap_write(void *context, const void *data, size_t count)
 {
-	struct rtl2832_priv *priv = mux_priv;
+	struct i2c_client *client = context;
 	int ret;
-	u8 buf[2], val;
 	struct i2c_msg msg[1] = {
 		{
-			.addr = priv->cfg.i2c_addr,
+			.addr = client->addr,
 			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
+			.len = count,
+			.buf = (u8 *)data,
 		}
 	};
-	struct i2c_msg msg_rd[2] = {
+
+	ret = __i2c_transfer(client->adapter, msg, 1);
+	if (ret != 1) {
+		dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
+		if (ret >= 0)
+			ret = -EREMOTEIO;
+		return ret;
+	}
+	return 0;
+}
+
+static int rtl2832_regmap_gather_write(void *context, const void *reg,
+				       size_t reg_len, const void *val,
+				       size_t val_len)
+{
+	struct i2c_client *client = context;
+	int ret;
+	u8 buf[256];
+	struct i2c_msg msg[1] = {
 		{
-			.addr = priv->cfg.i2c_addr,
+			.addr = client->addr,
 			.flags = 0,
-			.len = 1,
-			.buf = "\x01",
-		}, {
-			.addr = priv->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = 1,
-			.buf = &val,
+			.len = 1 + val_len,
+			.buf = buf,
 		}
 	};
 
-	/* terminate possible gate closing */
-	cancel_delayed_work_sync(&priv->i2c_gate_work);
+	buf[0] = *(u8 const *)reg;
+	memcpy(&buf[1], val, val_len);
 
-	if (priv->i2c_gate_state == chan_id)
-		return 0;
-
-	/* select reg bank 1 */
-	buf[0] = 0x00;
-	buf[1] = 0x01;
-	ret = __i2c_transfer(adap, msg, 1);
-	if (ret != 1)
-		goto err;
-
-	priv->page = 1;
+	ret = __i2c_transfer(client->adapter, msg, 1);
+	if (ret != 1) {
+		dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
+		if (ret >= 0)
+			ret = -EREMOTEIO;
+		return ret;
+	}
+	return 0;
+}
 
-	/* we must read that register, otherwise there will be errors */
-	ret = __i2c_transfer(adap, msg_rd, 2);
-	if (ret != 2)
-		goto err;
+/*
+ * FIXME: Hack. Implement own regmap locking in order to silence lockdep
+ * recursive lock warning. That happens when regmap I2C client calls I2C mux
+ * adapter, which leads demod I2C repeater enable via demod regmap. Operation
+ * takes two regmap locks recursively - but those are different regmap instances
+ * in a two different I2C drivers, so it is not deadlock. Proper fix is to make
+ * regmap aware of lockdep.
+ */
+static void rtl2832_regmap_lock(void *__dev)
+{
+	struct rtl2832_dev *dev = __dev;
+	struct i2c_client *client = dev->client;
 
-	/* open or close I2C repeater gate */
-	buf[0] = 0x01;
-	if (chan_id == 1)
-		buf[1] = 0x18; /* open */
-	else
-		buf[1] = 0x10; /* close */
+	dev_dbg(&client->dev, "\n");
+	mutex_lock(&dev->regmap_mutex);
+}
 
-	ret = __i2c_transfer(adap, msg, 1);
-	if (ret != 1)
-		goto err;
+static void rtl2832_regmap_unlock(void *__dev)
+{
+	struct rtl2832_dev *dev = __dev;
+	struct i2c_client *client = dev->client;
 
-	priv->i2c_gate_state = chan_id;
+	dev_dbg(&client->dev, "\n");
+	mutex_unlock(&dev->regmap_mutex);
+}
 
-	return 0;
-err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
+{
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
 
-	return -EREMOTEIO;
+	dev_dbg(&client->dev, "\n");
+	return &dev->fe;
 }
 
-static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
-		u32 chan_id)
+static struct i2c_adapter *rtl2832_get_i2c_adapter(struct i2c_client *client)
 {
-	struct rtl2832_priv *priv = mux_priv;
-	schedule_delayed_work(&priv->i2c_gate_work, usecs_to_jiffies(100));
-	return 0;
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "\n");
+	return dev->i2c_adapter_tuner;
 }
 
-int rtl2832_enable_external_ts_if(struct dvb_frontend *fe)
+static int rtl2832_enable_slave_ts(struct i2c_client *client)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
 	int ret;
 
-	dev_dbg(&priv->i2c->dev, "%s: setting PIP mode\n", __func__);
+	dev_dbg(&client->dev, "\n");
 
-	ret = rtl2832_wr_regs(priv, 0x0c, 1, "\x5f\xff", 2);
+	ret = rtl2832_bulk_write(client, 0x10c, "\x5f\xff", 2);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_demod_reg(priv, DVBT_PIP_ON, 0x1);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_PIP_ON, 0x1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_reg(priv, 0xbc, 0, 0x18);
+	ret = rtl2832_bulk_write(client, 0x0bc, "\x18", 1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_reg(priv, 0x22, 0, 0x01);
+	ret = rtl2832_bulk_write(client, 0x022, "\x01", 1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_reg(priv, 0x26, 0, 0x1f);
+	ret = rtl2832_bulk_write(client, 0x026, "\x1f", 1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_reg(priv, 0x27, 0, 0xff);
+	ret = rtl2832_bulk_write(client, 0x027, "\xff", 1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_regs(priv, 0x92, 1, "\x7f\xf7\xff", 3);
+	ret = rtl2832_bulk_write(client, 0x192, "\x7f\xf7\xff", 3);
 	if (ret)
 		goto err;
 
 	/* soft reset */
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
+	ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0);
 	if (ret)
 		goto err;
 
 	return 0;
 err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
-
 }
-EXPORT_SYMBOL(rtl2832_enable_external_ts_if);
 
-struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
+static int rtl2832_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	return priv->i2c_adapter_tuner;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
+	int ret;
+	u8 u8tmp;
+
+	dev_dbg(&client->dev, "onoff=%d\n", onoff);
+
+	/* enable / disable PID filter */
+	if (onoff)
+		u8tmp = 0x80;
+	else
+		u8tmp = 0x00;
+
+	ret = rtl2832_update_bits(client, 0x061, 0xc0, u8tmp);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
 }
-EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
 
-struct i2c_adapter *rtl2832_get_private_i2c_adapter(struct dvb_frontend *fe)
+static int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid,
+			      int onoff)
 {
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	return priv->i2c_adapter;
+	struct rtl2832_dev *dev = fe->demodulator_priv;
+	struct i2c_client *client = dev->client;
+	int ret;
+	u8 buf[4];
+
+	dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n",
+		index, pid, onoff);
+
+	/* skip invalid PIDs (0x2000) */
+	if (pid > 0x1fff || index > 32)
+		return 0;
+
+	if (onoff)
+		set_bit(index, &dev->filters);
+	else
+		clear_bit(index, &dev->filters);
+
+	/* enable / disable PIDs */
+	buf[0] = (dev->filters >>  0) & 0xff;
+	buf[1] = (dev->filters >>  8) & 0xff;
+	buf[2] = (dev->filters >> 16) & 0xff;
+	buf[3] = (dev->filters >> 24) & 0xff;
+	ret = rtl2832_bulk_write(client, 0x062, buf, 4);
+	if (ret)
+		goto err;
+
+	/* add PID */
+	buf[0] = (pid >> 8) & 0xff;
+	buf[1] = (pid >> 0) & 0xff;
+	ret = rtl2832_bulk_write(client, 0x066 + 2 * index, buf, 2);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
 }
-EXPORT_SYMBOL(rtl2832_get_private_i2c_adapter);
 
-struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
-	struct i2c_adapter *i2c)
+static int rtl2832_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
 {
-	struct rtl2832_priv *priv = NULL;
-	int ret = 0;
+	struct rtl2832_platform_data *pdata = client->dev.platform_data;
+	struct i2c_adapter *i2c = client->adapter;
+	struct rtl2832_dev *dev;
+	int ret;
 	u8 tmp;
+	static const struct regmap_bus regmap_bus = {
+		.read = rtl2832_regmap_read,
+		.write = rtl2832_regmap_write,
+		.gather_write = rtl2832_regmap_gather_write,
+		.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	};
+	static const struct regmap_range_cfg regmap_range_cfg[] = {
+		{
+			.selector_reg     = 0x00,
+			.selector_mask    = 0xff,
+			.selector_shift   = 0,
+			.window_start     = 0,
+			.window_len       = 0x100,
+			.range_min        = 0 * 0x100,
+			.range_max        = 5 * 0x100,
+		},
+	};
 
-	dev_dbg(&i2c->dev, "%s:\n", __func__);
+	dev_dbg(&client->dev, "\n");
 
 	/* allocate memory for the internal state */
-	priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
-	if (priv == NULL)
+	dev = kzalloc(sizeof(struct rtl2832_dev), GFP_KERNEL);
+	if (dev == NULL) {
+		ret = -ENOMEM;
 		goto err;
+	}
 
-	/* setup the priv */
-	priv->i2c = i2c;
-	priv->tuner = cfg->tuner;
-	memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
-	INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work);
-
-	/* create muxed i2c adapter for demod itself */
-	priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
-			rtl2832_select, NULL);
-	if (priv->i2c_adapter == NULL)
-		goto err;
+	/* setup the state */
+	i2c_set_clientdata(client, dev);
+	dev->client = client;
+	dev->pdata = client->dev.platform_data;
+	dev->sleeping = true;
+	INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work);
+	INIT_DELAYED_WORK(&dev->stat_work, rtl2832_stat_work);
+	/* create regmap */
+	mutex_init(&dev->regmap_mutex);
+	dev->regmap_config.reg_bits =  8,
+	dev->regmap_config.val_bits =  8,
+	dev->regmap_config.lock = rtl2832_regmap_lock,
+	dev->regmap_config.unlock = rtl2832_regmap_unlock,
+	dev->regmap_config.lock_arg = dev,
+	dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
+	dev->regmap_config.max_register = 5 * 0x100,
+	dev->regmap_config.ranges = regmap_range_cfg,
+	dev->regmap_config.num_ranges = ARRAY_SIZE(regmap_range_cfg),
+	dev->regmap_config.cache_type = REGCACHE_RBTREE,
+	dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
+				  &dev->regmap_config);
+	if (IS_ERR(dev->regmap)) {
+		ret = PTR_ERR(dev->regmap);
+		goto err_kfree;
+	}
 
 	/* check if the demod is there */
-	ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
+	ret = rtl2832_bulk_read(client, 0x000, &tmp, 1);
 	if (ret)
-		goto err;
+		goto err_regmap_exit;
 
 	/* create muxed i2c adapter for demod tuner bus */
-	priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
-			0, 1, 0, rtl2832_select, rtl2832_deselect);
-	if (priv->i2c_adapter_tuner == NULL)
-		goto err;
+	dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev,
+			0, 0, 0, rtl2832_select, rtl2832_deselect);
+	if (dev->i2c_adapter_tuner == NULL) {
+		ret = -ENODEV;
+		goto err_regmap_exit;
+	}
 
 	/* create dvb_frontend */
-	memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-
-	/* TODO implement sleep mode */
-	priv->sleeping = true;
-
-	return &priv->fe;
+	memcpy(&dev->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
+	dev->fe.demodulator_priv = dev;
+
+	/* setup callbacks */
+	pdata->get_dvb_frontend = rtl2832_get_dvb_frontend;
+	pdata->get_i2c_adapter = rtl2832_get_i2c_adapter;
+	pdata->enable_slave_ts = rtl2832_enable_slave_ts;
+	pdata->pid_filter = rtl2832_pid_filter;
+	pdata->pid_filter_ctrl = rtl2832_pid_filter_ctrl;
+	pdata->bulk_read = rtl2832_bulk_read;
+	pdata->bulk_write = rtl2832_bulk_write;
+	pdata->update_bits = rtl2832_update_bits;
+
+	dev_info(&client->dev, "Realtek RTL2832 successfully attached\n");
+	return 0;
+err_regmap_exit:
+	regmap_exit(dev->regmap);
+err_kfree:
+	kfree(dev);
 err:
-	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
-	if (priv && priv->i2c_adapter)
-		i2c_del_mux_adapter(priv->i2c_adapter);
-	kfree(priv);
-	return NULL;
+	dev_dbg(&client->dev, "failed=%d\n", ret);
+	return ret;
 }
-EXPORT_SYMBOL(rtl2832_attach);
 
-static struct dvb_frontend_ops rtl2832_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Realtek RTL2832 (DVB-T)",
-		.frequency_min	  = 174000000,
-		.frequency_max	  = 862000000,
-		.frequency_stepsize = 166667,
-		.caps = FE_CAN_FEC_1_2 |
-			FE_CAN_FEC_2_3 |
-			FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 |
-			FE_CAN_FEC_7_8 |
-			FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	 },
+static int rtl2832_remove(struct i2c_client *client)
+{
+	struct rtl2832_dev *dev = i2c_get_clientdata(client);
 
-	.release = rtl2832_release,
+	dev_dbg(&client->dev, "\n");
 
-	.init = rtl2832_init,
-	.sleep = rtl2832_sleep,
+	cancel_delayed_work_sync(&dev->i2c_gate_work);
 
-	.get_tune_settings = rtl2832_get_tune_settings,
+	i2c_del_mux_adapter(dev->i2c_adapter_tuner);
 
-	.set_frontend = rtl2832_set_frontend,
-	.get_frontend = rtl2832_get_frontend,
+	regmap_exit(dev->regmap);
 
-	.read_status = rtl2832_read_status,
-	.read_snr = rtl2832_read_snr,
-	.read_ber = rtl2832_read_ber,
+	kfree(dev);
 
-	.i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
+	return 0;
+}
+
+static const struct i2c_device_id rtl2832_id_table[] = {
+	{"rtl2832", 0},
+	{}
 };
+MODULE_DEVICE_TABLE(i2c, rtl2832_id_table);
+
+static struct i2c_driver rtl2832_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "rtl2832",
+	},
+	.probe		= rtl2832_probe,
+	.remove		= rtl2832_remove,
+	.id_table	= rtl2832_id_table,
+};
+
+module_i2c_driver(rtl2832_driver);
 
 MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.5");
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index 5254c1dfc8de..a8e912e679a5 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -2,6 +2,7 @@
  * Realtek RTL2832 DVB-T demodulator driver
  *
  * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
+ * Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi>
  *
  *	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
@@ -21,86 +22,42 @@
 #ifndef RTL2832_H
 #define RTL2832_H
 
-#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
+#include <linux/i2c-mux.h>
+
+/**
+ * struct rtl2832_platform_data - Platform data for the rtl2832 driver
+ * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
+ * @tuner: Used tuner model.
+ * @get_dvb_frontend: Get DVB frontend.
+ * @get_i2c_adapter: Get I2C adapter.
+ * @enable_slave_ts: Enable slave TS IF.
+ * @pid_filter: Set PID to PID filter.
+ * @pid_filter_ctrl: Control PID filter.
+ */
 
-struct rtl2832_config {
-	/*
-	 * Demodulator I2C address.
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * Xtal frequency.
-	 * Hz
-	 * 4000000, 16000000, 25000000, 28800000
-	 */
-	u32 xtal;
-
+struct rtl2832_platform_data {
+	u32 clk;
 	/*
-	 * tuner
-	 * XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver.
+	 * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
 	 */
 #define RTL2832_TUNER_TUA9001   0x24
 #define RTL2832_TUNER_FC0012    0x26
 #define RTL2832_TUNER_E4000     0x27
 #define RTL2832_TUNER_FC0013    0x29
-#define RTL2832_TUNER_R820T	0x2a
-#define RTL2832_TUNER_R828D	0x2b
+#define RTL2832_TUNER_R820T     0x2a
+#define RTL2832_TUNER_R828D     0x2b
 	u8 tuner;
-};
-
-#if IS_ENABLED(CONFIG_DVB_RTL2832)
-struct dvb_frontend *rtl2832_attach(
-	const struct rtl2832_config *cfg,
-	struct i2c_adapter *i2c
-);
-
-extern struct i2c_adapter *rtl2832_get_i2c_adapter(
-	struct dvb_frontend *fe
-);
-
-extern struct i2c_adapter *rtl2832_get_private_i2c_adapter(
-	struct dvb_frontend *fe
-);
-
-extern int rtl2832_enable_external_ts_if(
-	struct dvb_frontend *fe
-);
-
-#else
-
-static inline struct dvb_frontend *rtl2832_attach(
-	const struct rtl2832_config *config,
-	struct i2c_adapter *i2c
-)
-{
-	pr_warn("%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *rtl2832_get_i2c_adapter(
-	struct dvb_frontend *fe
-)
-{
-	return NULL;
-}
-
-static inline struct i2c_adapter *rtl2832_get_private_i2c_adapter(
-	struct dvb_frontend *fe
-)
-{
-	return NULL;
-}
-
-static inline int rtl2832_enable_external_ts_if(
-	struct dvb_frontend *fe
-)
-{
-	return -ENODEV;
-}
-
-#endif
 
+	struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
+	struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
+	int (*enable_slave_ts)(struct i2c_client *);
+	int (*pid_filter)(struct dvb_frontend *, u8, u16, int);
+	int (*pid_filter_ctrl)(struct dvb_frontend *, int);
+/* private: Register access for SDR module use only */
+	int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t);
+	int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t);
+	int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int);
+};
 
 #endif /* RTL2832_H */
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
index ae469f032fe6..c3a922c37903 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -2,6 +2,7 @@
  * Realtek RTL2832 DVB-T demodulator driver
  *
  * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
+ * Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi>
  *
  *	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
@@ -21,28 +22,34 @@
 #ifndef RTL2832_PRIV_H
 #define RTL2832_PRIV_H
 
+#include <linux/regmap.h>
+#include <linux/math64.h>
+#include <linux/bitops.h>
+
 #include "dvb_frontend.h"
+#include "dvb_math.h"
 #include "rtl2832.h"
-#include <linux/i2c-mux.h>
 
-struct rtl2832_priv {
-	struct i2c_adapter *i2c;
-	struct i2c_adapter *i2c_adapter;
+struct rtl2832_dev {
+	struct rtl2832_platform_data *pdata;
+	struct i2c_client *client;
+	struct mutex regmap_mutex;
+	struct regmap_config regmap_config;
+	struct regmap *regmap;
 	struct i2c_adapter *i2c_adapter_tuner;
 	struct dvb_frontend fe;
-	struct rtl2832_config cfg;
-
-	bool i2c_gate_state;
+	struct delayed_work stat_work;
+	fe_status_t fe_status;
+	u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
+	u64 post_bit_error;
+	u64 post_bit_count;
 	bool sleeping;
-
-	u8 tuner;
-	u8 page; /* active register page */
 	struct delayed_work i2c_gate_work;
+	unsigned long filters; /* PID filter */
 };
 
 struct rtl2832_reg_entry {
-	u8 page;
-	u8 start_address;
+	u16 start_address;
 	u8 msb;
 	u8 lsb;
 };
@@ -52,7 +59,6 @@ struct rtl2832_reg_value {
 	u32 value;
 };
 
-
 /* Demod register bit names */
 enum DVBT_REG_BIT_NAME {
 	DVBT_SOFT_RST,
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 2896b47c29d8..3ff8806ca584 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -22,7 +22,6 @@
  *
  */
 
-#include "dvb_frontend.h"
 #include "rtl2832_sdr.h"
 #include "dvb_usb.h"
 
@@ -32,6 +31,7 @@
 #include <media/v4l2-event.h>
 #include <media/videobuf2-vmalloc.h>
 
+#include <linux/platform_device.h>
 #include <linux/jiffies.h>
 #include <linux/math64.h>
 
@@ -107,16 +107,12 @@ struct rtl2832_sdr_frame_buf {
 	struct list_head list;
 };
 
-struct rtl2832_sdr_state {
+struct rtl2832_sdr_dev {
 #define POWER_ON           (1 << 1)
 #define URB_BUF            (1 << 2)
 	unsigned long flags;
 
-	const struct rtl2832_config *cfg;
-	struct dvb_frontend *fe;
-	struct dvb_usb_device *d;
-	struct i2c_adapter *i2c;
-	u8 bank;
+	struct platform_device *pdev;
 
 	struct video_device vdev;
 	struct v4l2_device v4l2_dev;
@@ -160,200 +156,77 @@ struct rtl2832_sdr_state {
 	unsigned long jiffies_next;
 };
 
-/* write multiple hardware registers */
-static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val,
-		int len)
-{
-	int ret;
-#define MAX_WR_LEN 24
-#define MAX_WR_XFER_LEN (MAX_WR_LEN + 1)
-	u8 buf[MAX_WR_XFER_LEN];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = s->cfg->i2c_addr,
-			.flags = 0,
-			.len = 1 + len,
-			.buf = buf,
-		}
-	};
-
-	if (WARN_ON(len > MAX_WR_LEN))
-		return -EINVAL;
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(s->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_err(&s->i2c->dev,
-			"%s: I2C wr failed=%d reg=%02x len=%d\n",
-			KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple hardware registers */
-static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len)
-{
-	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = s->cfg->i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = s->cfg->i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	ret = i2c_transfer(s->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		dev_err(&s->i2c->dev,
-				"%s: I2C rd failed=%d reg=%02x len=%d\n",
-				KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
 /* write multiple registers */
-static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg,
+static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg,
 		const u8 *val, int len)
 {
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 bank = (reg >> 8) & 0xff;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct i2c_client *client = pdata->i2c_client;
 
-	/* switch bank if needed */
-	if (bank != s->bank) {
-		ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
-		if (ret)
-			return ret;
-
-		s->bank = bank;
-	}
-
-	return rtl2832_sdr_wr(s, reg2, val, len);
+	return pdata->bulk_write(client, reg, val, len);
 }
 
+#if 0
 /* read multiple registers */
-static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val,
+static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val,
 		int len)
 {
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 bank = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (bank != s->bank) {
-		ret = rtl2832_sdr_wr(s, 0x00, &bank, 1);
-		if (ret)
-			return ret;
-
-		s->bank = bank;
-	}
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct i2c_client *client = pdata->i2c_client;
 
-	return rtl2832_sdr_rd(s, reg2, val, len);
+	return pdata->bulk_read(client, reg, val, len);
 }
+#endif
 
 /* write single register */
-static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val)
+static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val)
 {
-	return rtl2832_sdr_wr_regs(s, reg, &val, 1);
+	return rtl2832_sdr_wr_regs(dev, reg, &val, 1);
 }
 
-#if 0
-/* read single register */
-static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val)
-{
-	return rtl2832_sdr_rd_regs(s, reg, val, 1);
-}
-#endif
-
 /* write single register with mask */
-static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
+static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg,
 		u8 val, u8 mask)
 {
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return rtl2832_sdr_wr_regs(s, reg, &val, 1);
-}
-
-#if 0
-/* read single register with mask */
-static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg,
-		u8 *val, u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct i2c_client *client = pdata->i2c_client;
 
-	return 0;
+	return pdata->update_bits(client, reg, mask, val);
 }
-#endif
 
 /* Private functions */
 static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
-		struct rtl2832_sdr_state *s)
+		struct rtl2832_sdr_dev *dev)
 {
 	unsigned long flags;
 	struct rtl2832_sdr_frame_buf *buf = NULL;
 
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	if (list_empty(&s->queued_bufs))
+	spin_lock_irqsave(&dev->queued_bufs_lock, flags);
+	if (list_empty(&dev->queued_bufs))
 		goto leave;
 
-	buf = list_entry(s->queued_bufs.next,
+	buf = list_entry(dev->queued_bufs.next,
 			struct rtl2832_sdr_frame_buf, list);
 	list_del(&buf->list);
 leave:
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 	return buf;
 }
 
-static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
+static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_dev *dev,
 		void *dst, const u8 *src, unsigned int src_len)
 {
+	struct platform_device *pdev = dev->pdev;
 	unsigned int dst_len;
 
-	if (s->pixelformat ==  V4L2_SDR_FMT_CU8) {
+	if (dev->pixelformat ==  V4L2_SDR_FMT_CU8) {
 		/* native stream, no need to convert */
 		memcpy(dst, src, src_len);
 		dst_len = src_len;
-	} else if (s->pixelformat == V4L2_SDR_FMT_CU16LE) {
+	} else if (dev->pixelformat == V4L2_SDR_FMT_CU16LE) {
 		/* convert u8 to u16 */
 		unsigned int i;
 		u16 *u16dst = dst;
@@ -366,22 +239,21 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
 	}
 
 	/* calculate sample rate and output it in 10 seconds intervals */
-	if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+	if (unlikely(time_is_before_jiffies(dev->jiffies_next))) {
 		#define MSECS 10000UL
 		unsigned int msecs = jiffies_to_msecs(jiffies -
-				s->jiffies_next + msecs_to_jiffies(MSECS));
-		unsigned int samples = s->sample - s->sample_measured;
-
-		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
-		s->sample_measured = s->sample;
-		dev_dbg(&s->udev->dev,
-				"slen=%u samples=%u msecs=%u sample rate=%lu\n",
-				src_len, samples, msecs,
-				samples * 1000UL / msecs);
+				dev->jiffies_next + msecs_to_jiffies(MSECS));
+		unsigned int samples = dev->sample - dev->sample_measured;
+
+		dev->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+		dev->sample_measured = dev->sample;
+		dev_dbg(&pdev->dev,
+			"slen=%u samples=%u msecs=%u sample rate=%lu\n",
+			src_len, samples, msecs, samples * 1000UL / msecs);
 	}
 
 	/* total number of I+Q pairs */
-	s->sample += src_len / 2;
+	dev->sample += src_len / 2;
 
 	return dst_len;
 }
@@ -392,13 +264,13 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
  */
 static void rtl2832_sdr_urb_complete(struct urb *urb)
 {
-	struct rtl2832_sdr_state *s = urb->context;
+	struct rtl2832_sdr_dev *dev = urb->context;
+	struct platform_device *pdev = dev->pdev;
 	struct rtl2832_sdr_frame_buf *fbuf;
 
-	dev_dbg_ratelimited(&s->udev->dev,
-			"status=%d length=%d/%d errors=%d\n",
-			urb->status, urb->actual_length,
-			urb->transfer_buffer_length, urb->error_count);
+	dev_dbg_ratelimited(&pdev->dev, "status=%d length=%d/%d errors=%d\n",
+			    urb->status, urb->actual_length,
+			    urb->transfer_buffer_length, urb->error_count);
 
 	switch (urb->status) {
 	case 0:             /* success */
@@ -409,8 +281,7 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
 	case -ESHUTDOWN:
 		return;
 	default:            /* error */
-		dev_err_ratelimited(&s->udev->dev, "urb failed=%d\n",
-				urb->status);
+		dev_err_ratelimited(&pdev->dev, "urb failed=%d\n", urb->status);
 		break;
 	}
 
@@ -418,204 +289,192 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
 		void *ptr;
 		unsigned int len;
 		/* get free framebuffer */
-		fbuf = rtl2832_sdr_get_next_fill_buf(s);
+		fbuf = rtl2832_sdr_get_next_fill_buf(dev);
 		if (unlikely(fbuf == NULL)) {
-			s->vb_full++;
-			dev_notice_ratelimited(&s->udev->dev,
-					"videobuf is full, %d packets dropped\n",
-					s->vb_full);
+			dev->vb_full++;
+			dev_notice_ratelimited(&pdev->dev,
+					       "videobuf is full, %d packets dropped\n",
+					       dev->vb_full);
 			goto skip;
 		}
 
 		/* fill framebuffer */
 		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		len = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer,
+		len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer,
 				urb->actual_length);
 		vb2_set_plane_payload(&fbuf->vb, 0, len);
 		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
-		fbuf->vb.v4l2_buf.sequence = s->sequence++;
+		fbuf->vb.v4l2_buf.sequence = dev->sequence++;
 		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
 	}
 skip:
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
-static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_dev *dev)
 {
+	struct platform_device *pdev = dev->pdev;
 	int i;
 
-	for (i = s->urbs_submitted - 1; i >= 0; i--) {
-		dev_dbg(&s->udev->dev, "kill urb=%d\n", i);
+	for (i = dev->urbs_submitted - 1; i >= 0; i--) {
+		dev_dbg(&pdev->dev, "kill urb=%d\n", i);
 		/* stop the URB */
-		usb_kill_urb(s->urb_list[i]);
+		usb_kill_urb(dev->urb_list[i]);
 	}
-	s->urbs_submitted = 0;
+	dev->urbs_submitted = 0;
 
 	return 0;
 }
 
-static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_dev *dev)
 {
+	struct platform_device *pdev = dev->pdev;
 	int i, ret;
 
-	for (i = 0; i < s->urbs_initialized; i++) {
-		dev_dbg(&s->udev->dev, "submit urb=%d\n", i);
-		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
+	for (i = 0; i < dev->urbs_initialized; i++) {
+		dev_dbg(&pdev->dev, "submit urb=%d\n", i);
+		ret = usb_submit_urb(dev->urb_list[i], GFP_ATOMIC);
 		if (ret) {
-			dev_err(&s->udev->dev,
-					"Could not submit urb no. %d - get them all back\n",
-					i);
-			rtl2832_sdr_kill_urbs(s);
+			dev_err(&pdev->dev,
+				"Could not submit urb no. %d - get them all back\n",
+				i);
+			rtl2832_sdr_kill_urbs(dev);
 			return ret;
 		}
-		s->urbs_submitted++;
+		dev->urbs_submitted++;
 	}
 
 	return 0;
 }
 
-static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev)
 {
-	if (s->flags & USB_STATE_URB_BUF) {
-		while (s->buf_num) {
-			s->buf_num--;
-			dev_dbg(&s->udev->dev, "free buf=%d\n", s->buf_num);
-			usb_free_coherent(s->udev, s->buf_size,
-					  s->buf_list[s->buf_num],
-					  s->dma_addr[s->buf_num]);
+	struct platform_device *pdev = dev->pdev;
+
+	if (dev->flags & USB_STATE_URB_BUF) {
+		while (dev->buf_num) {
+			dev->buf_num--;
+			dev_dbg(&pdev->dev, "free buf=%d\n", dev->buf_num);
+			usb_free_coherent(dev->udev, dev->buf_size,
+					  dev->buf_list[dev->buf_num],
+					  dev->dma_addr[dev->buf_num]);
 		}
 	}
-	s->flags &= ~USB_STATE_URB_BUF;
+	dev->flags &= ~USB_STATE_URB_BUF;
 
 	return 0;
 }
 
-static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev)
 {
-	s->buf_num = 0;
-	s->buf_size = BULK_BUFFER_SIZE;
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "all in all I will use %u bytes for streaming\n",
-			MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+	dev->buf_num = 0;
+	dev->buf_size = BULK_BUFFER_SIZE;
 
-	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
-		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
+	dev_dbg(&pdev->dev, "all in all I will use %u bytes for streaming\n",
+		MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+
+	for (dev->buf_num = 0; dev->buf_num < MAX_BULK_BUFS; dev->buf_num++) {
+		dev->buf_list[dev->buf_num] = usb_alloc_coherent(dev->udev,
 				BULK_BUFFER_SIZE, GFP_ATOMIC,
-				&s->dma_addr[s->buf_num]);
-		if (!s->buf_list[s->buf_num]) {
-			dev_dbg(&s->udev->dev, "alloc buf=%d failed\n",
-					s->buf_num);
-			rtl2832_sdr_free_stream_bufs(s);
+				&dev->dma_addr[dev->buf_num]);
+		if (!dev->buf_list[dev->buf_num]) {
+			dev_dbg(&pdev->dev, "alloc buf=%d failed\n",
+				dev->buf_num);
+			rtl2832_sdr_free_stream_bufs(dev);
 			return -ENOMEM;
 		}
 
-		dev_dbg(&s->udev->dev, "alloc buf=%d %p (dma %llu)\n",
-				s->buf_num, s->buf_list[s->buf_num],
-				(long long)s->dma_addr[s->buf_num]);
-		s->flags |= USB_STATE_URB_BUF;
+		dev_dbg(&pdev->dev, "alloc buf=%d %p (dma %llu)\n",
+			dev->buf_num, dev->buf_list[dev->buf_num],
+			(long long)dev->dma_addr[dev->buf_num]);
+		dev->flags |= USB_STATE_URB_BUF;
 	}
 
 	return 0;
 }
 
-static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_dev *dev)
 {
+	struct platform_device *pdev = dev->pdev;
 	int i;
 
-	rtl2832_sdr_kill_urbs(s);
+	rtl2832_sdr_kill_urbs(dev);
 
-	for (i = s->urbs_initialized - 1; i >= 0; i--) {
-		if (s->urb_list[i]) {
-			dev_dbg(&s->udev->dev, "free urb=%d\n", i);
+	for (i = dev->urbs_initialized - 1; i >= 0; i--) {
+		if (dev->urb_list[i]) {
+			dev_dbg(&pdev->dev, "free urb=%d\n", i);
 			/* free the URBs */
-			usb_free_urb(s->urb_list[i]);
+			usb_free_urb(dev->urb_list[i]);
 		}
 	}
-	s->urbs_initialized = 0;
+	dev->urbs_initialized = 0;
 
 	return 0;
 }
 
-static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_dev *dev)
 {
+	struct platform_device *pdev = dev->pdev;
 	int i, j;
 
 	/* allocate the URBs */
 	for (i = 0; i < MAX_BULK_BUFS; i++) {
-		dev_dbg(&s->udev->dev, "alloc urb=%d\n", i);
-		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
-		if (!s->urb_list[i]) {
-			dev_dbg(&s->udev->dev, "failed\n");
+		dev_dbg(&pdev->dev, "alloc urb=%d\n", i);
+		dev->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!dev->urb_list[i]) {
+			dev_dbg(&pdev->dev, "failed\n");
 			for (j = 0; j < i; j++)
-				usb_free_urb(s->urb_list[j]);
+				usb_free_urb(dev->urb_list[j]);
 			return -ENOMEM;
 		}
-		usb_fill_bulk_urb(s->urb_list[i],
-				s->udev,
-				usb_rcvbulkpipe(s->udev, 0x81),
-				s->buf_list[i],
+		usb_fill_bulk_urb(dev->urb_list[i],
+				dev->udev,
+				usb_rcvbulkpipe(dev->udev, 0x81),
+				dev->buf_list[i],
 				BULK_BUFFER_SIZE,
-				rtl2832_sdr_urb_complete, s);
+				rtl2832_sdr_urb_complete, dev);
 
-		s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-		s->urb_list[i]->transfer_dma = s->dma_addr[i];
-		s->urbs_initialized++;
+		dev->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+		dev->urb_list[i]->transfer_dma = dev->dma_addr[i];
+		dev->urbs_initialized++;
 	}
 
 	return 0;
 }
 
 /* Must be called with vb_queue_lock hold */
-static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
+static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev)
 {
+	struct platform_device *pdev = dev->pdev;
 	unsigned long flags;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	while (!list_empty(&s->queued_bufs)) {
+	spin_lock_irqsave(&dev->queued_bufs_lock, flags);
+	while (!list_empty(&dev->queued_bufs)) {
 		struct rtl2832_sdr_frame_buf *buf;
 
-		buf = list_entry(s->queued_bufs.next,
+		buf = list_entry(dev->queued_bufs.next,
 				struct rtl2832_sdr_frame_buf, list);
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	}
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
-}
-
-/* The user yanked out the cable... */
-static void rtl2832_sdr_release_sec(struct dvb_frontend *fe)
-{
-	struct rtl2832_sdr_state *s = fe->sec_priv;
-
-	dev_dbg(&s->udev->dev, "\n");
-
-	mutex_lock(&s->vb_queue_lock);
-	mutex_lock(&s->v4l2_lock);
-	/* No need to keep the urbs around after disconnection */
-	s->udev = NULL;
-
-	v4l2_device_disconnect(&s->v4l2_dev);
-	video_unregister_device(&s->vdev);
-	mutex_unlock(&s->v4l2_lock);
-	mutex_unlock(&s->vb_queue_lock);
-
-	v4l2_device_put(&s->v4l2_dev);
-
-	fe->sec_priv = NULL;
+	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 }
 
 static int rtl2832_sdr_querycap(struct file *file, void *fh,
 		struct v4l2_capability *cap)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
 	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
-	strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
-	usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
+	strlcpy(cap->card, dev->vdev.name, sizeof(cap->card));
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 	cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
 			V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -627,26 +486,26 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
 		const struct v4l2_format *fmt, unsigned int *nbuffers,
 		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "nbuffers=%d\n", *nbuffers);
+	dev_dbg(&pdev->dev, "nbuffers=%d\n", *nbuffers);
 
 	/* Need at least 8 buffers */
 	if (vq->num_buffers + *nbuffers < 8)
 		*nbuffers = 8 - vq->num_buffers;
 	*nplanes = 1;
-	sizes[0] = PAGE_ALIGN(s->buffersize);
-	dev_dbg(&s->udev->dev, "nbuffers=%d sizes[0]=%d\n",
-			*nbuffers, sizes[0]);
+	sizes[0] = PAGE_ALIGN(dev->buffersize);
+	dev_dbg(&pdev->dev, "nbuffers=%d sizes[0]=%d\n", *nbuffers, sizes[0]);
 	return 0;
 }
 
 static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
 {
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 
 	/* Don't allow queing new buffers after device disconnection */
-	if (!s->udev)
+	if (!dev->udev)
 		return -ENODEV;
 
 	return 0;
@@ -654,46 +513,48 @@ static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
 
 static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
 {
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	struct rtl2832_sdr_frame_buf *buf =
 			container_of(vb, struct rtl2832_sdr_frame_buf, vb);
 	unsigned long flags;
 
 	/* Check the device has not disconnected between prep and queuing */
-	if (!s->udev) {
+	if (!dev->udev) {
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 		return;
 	}
 
-	spin_lock_irqsave(&s->queued_bufs_lock, flags);
-	list_add_tail(&buf->list, &s->queued_bufs);
-	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+	spin_lock_irqsave(&dev->queued_bufs_lock, flags);
+	list_add_tail(&buf->list, &dev->queued_bufs);
+	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 }
 
-static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
 {
-	struct dvb_frontend *fe = s->fe;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
 	int ret;
 	unsigned int f_sr, f_if;
 	u8 buf[4], u8tmp1, u8tmp2;
 	u64 u64tmp;
 	u32 u32tmp;
 
-	dev_dbg(&s->udev->dev, "f_adc=%u\n", s->f_adc);
+	dev_dbg(&pdev->dev, "f_adc=%u\n", dev->f_adc);
 
-	if (!test_bit(POWER_ON, &s->flags))
+	if (!test_bit(POWER_ON, &dev->flags))
 		return 0;
 
-	if (s->f_adc == 0)
+	if (dev->f_adc == 0)
 		return 0;
 
-	f_sr = s->f_adc;
+	f_sr = dev->f_adc;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2);
+	ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x00\x00", 2);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00\x00\x00\x00", 4);
+	ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x00\x00\x00\x00", 4);
 	if (ret)
 		goto err;
 
@@ -707,19 +568,19 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
 		goto err;
 
 	/* program IF */
-	u64tmp = f_if % s->cfg->xtal;
+	u64tmp = f_if % pdata->clk;
 	u64tmp *= 0x400000;
-	u64tmp = div_u64(u64tmp, s->cfg->xtal);
+	u64tmp = div_u64(u64tmp, pdata->clk);
 	u64tmp = -u64tmp;
 	u32tmp = u64tmp & 0x3fffff;
 
-	dev_dbg(&s->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp);
+	dev_dbg(&pdev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp);
 
 	buf[0] = (u32tmp >> 16) & 0xff;
 	buf[1] = (u32tmp >>  8) & 0xff;
 	buf[2] = (u32tmp >>  0) & 0xff;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x119, buf, 3);
+	ret = rtl2832_sdr_wr_regs(dev, 0x119, buf, 3);
 	if (ret)
 		goto err;
 
@@ -733,208 +594,212 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
 		u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
 	}
 
-	ret = rtl2832_sdr_wr_reg(s, 0x1b1, u8tmp1);
+	ret = rtl2832_sdr_wr_reg(dev, 0x1b1, u8tmp1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_reg(s, 0x008, u8tmp2);
+	ret = rtl2832_sdr_wr_reg(dev, 0x008, u8tmp2);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_reg(s, 0x006, 0x80);
+	ret = rtl2832_sdr_wr_reg(dev, 0x006, 0x80);
 	if (ret)
 		goto err;
 
 	/* program sampling rate (resampling down) */
-	u32tmp = div_u64(s->cfg->xtal * 0x400000ULL, f_sr * 4U);
+	u32tmp = div_u64(pdata->clk * 0x400000ULL, f_sr * 4U);
 	u32tmp <<= 2;
 	buf[0] = (u32tmp >> 24) & 0xff;
 	buf[1] = (u32tmp >> 16) & 0xff;
 	buf[2] = (u32tmp >>  8) & 0xff;
 	buf[3] = (u32tmp >>  0) & 0xff;
-	ret = rtl2832_sdr_wr_regs(s, 0x19f, buf, 4);
+	ret = rtl2832_sdr_wr_regs(dev, 0x19f, buf, 4);
 	if (ret)
 		goto err;
 
 	/* low-pass filter */
-	ret = rtl2832_sdr_wr_regs(s, 0x11c,
+	ret = rtl2832_sdr_wr_regs(dev, 0x11c,
 			"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
 			20);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
+	ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2);
 	if (ret)
 		goto err;
 
 	/* mode */
-	ret = rtl2832_sdr_wr_regs(s, 0x019, "\x05", 1);
+	ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x05", 1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6);
+	ret = rtl2832_sdr_wr_regs(dev, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6);
 	if (ret)
 		goto err;
 
 	/* FSM */
-	ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\xf0\x0f", 3);
+	ret = rtl2832_sdr_wr_regs(dev, 0x192, "\x00\xf0\x0f", 3);
 	if (ret)
 		goto err;
 
 	/* PID filter */
-	ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1);
+	ret = rtl2832_sdr_wr_regs(dev, 0x061, "\x60", 1);
 	if (ret)
 		goto err;
 
 	/* used RF tuner based settings */
-	switch (s->cfg->tuner) {
-	case RTL2832_TUNER_E4000:
-		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1);
+	switch (pdata->tuner) {
+	case RTL2832_SDR_TUNER_E4000:
+		ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x30", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xd0", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x18", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xd4", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1e5, "\xf0", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1d9, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1db, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1dd, "\x14", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1de, "\xec", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1d8, "\x0c", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1e6, "\x02", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1d7, "\x09", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x83", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x010, "\x49", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x87", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x85", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x013, "\x02", 1);
 		break;
-	case RTL2832_TUNER_FC0012:
-	case RTL2832_TUNER_FC0013:
-		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1);
+	case RTL2832_SDR_TUNER_FC0012:
+	case RTL2832_SDR_TUNER_FC0013:
+		ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x2c", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x16", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xe9\xbf", 2);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1e5, "\xf0", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1d9, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1db, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1dd, "\x11", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1de, "\xef", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1d8, "\x0c", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1e6, "\x02", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1d7, "\x09", 1);
 		break;
-	case RTL2832_TUNER_R820T:
-		ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1);
-		ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1);
+	case RTL2832_SDR_TUNER_R820T:
+	case RTL2832_SDR_TUNER_R828D:
+		ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x01", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x24", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x14", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x80", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1);
+		ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xf4", 1);
 		break;
 	default:
-		dev_notice(&s->udev->dev, "Unsupported tuner\n");
+		dev_notice(&pdev->dev, "Unsupported tuner\n");
 	}
 
 	/* software reset */
-	ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x04, 0x04);
+	ret = rtl2832_sdr_wr_reg_mask(dev, 0x101, 0x04, 0x04);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x00, 0x04);
+	ret = rtl2832_sdr_wr_reg_mask(dev, 0x101, 0x00, 0x04);
 	if (ret)
 		goto err;
 err:
 	return ret;
 };
 
-static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s)
+static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_dev *dev)
 {
+	struct platform_device *pdev = dev->pdev;
 	int ret;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
 	/* PID filter */
-	ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1);
+	ret = rtl2832_sdr_wr_regs(dev, 0x061, "\xe0", 1);
 	if (ret)
 		goto err;
 
 	/* mode */
-	ret = rtl2832_sdr_wr_regs(s, 0x019, "\x20", 1);
+	ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x20", 1);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2);
+	ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2);
 	if (ret)
 		goto err;
 
 	/* FSM */
-	ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\x0f\xff", 3);
+	ret = rtl2832_sdr_wr_regs(dev, 0x192, "\x00\x0f\xff", 3);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x40\x00", 2);
+	ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x40\x00", 2);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_wr_regs(s, 0x115, "\x06\x3f\xce\xcc", 4);
+	ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x06\x3f\xce\xcc", 4);
 	if (ret)
 		goto err;
 err:
 	return;
 };
 
-static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev)
 {
-	struct dvb_frontend *fe = s->fe;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct v4l2_ctrl *bandwidth_auto;
 	struct v4l2_ctrl *bandwidth;
@@ -942,29 +807,29 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
 	/*
 	 * tuner RF (Hz)
 	 */
-	if (s->f_tuner == 0)
+	if (dev->f_tuner == 0)
 		return 0;
 
 	/*
 	 * bandwidth (Hz)
 	 */
-	bandwidth_auto = v4l2_ctrl_find(&s->hdl,
+	bandwidth_auto = v4l2_ctrl_find(&dev->hdl,
 					V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
-	bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
+	bandwidth = v4l2_ctrl_find(&dev->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
 	if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
-		c->bandwidth_hz = s->f_adc;
-		v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
+		c->bandwidth_hz = dev->f_adc;
+		v4l2_ctrl_s_ctrl(bandwidth, dev->f_adc);
 	} else {
 		c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth);
 	}
 
-	c->frequency = s->f_tuner;
+	c->frequency = dev->f_tuner;
 	c->delivery_system = SYS_DVBT;
 
-	dev_dbg(&s->udev->dev, "frequency=%u bandwidth=%d\n",
-			c->frequency, c->bandwidth_hz);
+	dev_dbg(&pdev->dev, "frequency=%u bandwidth=%d\n",
+		c->frequency, c->bandwidth_hz);
 
-	if (!test_bit(POWER_ON, &s->flags))
+	if (!test_bit(POWER_ON, &dev->flags))
 		return 0;
 
 	if (fe->ops.tuner_ops.set_params)
@@ -973,11 +838,13 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
 	return 0;
 };
 
-static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
+static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_dev *dev)
 {
-	struct dvb_frontend *fe = s->fe;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
 	if (fe->ops.tuner_ops.init)
 		fe->ops.tuner_ops.init(fe);
@@ -985,11 +852,13 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s)
 	return 0;
 };
 
-static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
+static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_dev *dev)
 {
-	struct dvb_frontend *fe = s->fe;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
 	if (fe->ops.tuner_ops.sleep)
 		fe->ops.tuner_ops.sleep(fe);
@@ -999,83 +868,89 @@ static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s)
 
 static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_usb_device *d = pdata->dvb_usb_device;
 	int ret;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
-	if (!s->udev)
+	if (!dev->udev)
 		return -ENODEV;
 
-	if (mutex_lock_interruptible(&s->v4l2_lock))
+	if (mutex_lock_interruptible(&dev->v4l2_lock))
 		return -ERESTARTSYS;
 
-	if (s->d->props->power_ctrl)
-		s->d->props->power_ctrl(s->d, 1);
+	if (d->props->power_ctrl)
+		d->props->power_ctrl(d, 1);
 
 	/* enable ADC */
-	if (s->d->props->frontend_ctrl)
-		s->d->props->frontend_ctrl(s->fe, 1);
+	if (d->props->frontend_ctrl)
+		d->props->frontend_ctrl(pdata->dvb_frontend, 1);
 
-	set_bit(POWER_ON, &s->flags);
+	set_bit(POWER_ON, &dev->flags);
 
-	ret = rtl2832_sdr_set_tuner(s);
+	ret = rtl2832_sdr_set_tuner(dev);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_set_tuner_freq(s);
+	ret = rtl2832_sdr_set_tuner_freq(dev);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_set_adc(s);
+	ret = rtl2832_sdr_set_adc(dev);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_alloc_stream_bufs(s);
+	ret = rtl2832_sdr_alloc_stream_bufs(dev);
 	if (ret)
 		goto err;
 
-	ret = rtl2832_sdr_alloc_urbs(s);
+	ret = rtl2832_sdr_alloc_urbs(dev);
 	if (ret)
 		goto err;
 
-	s->sequence = 0;
+	dev->sequence = 0;
 
-	ret = rtl2832_sdr_submit_urbs(s);
+	ret = rtl2832_sdr_submit_urbs(dev);
 	if (ret)
 		goto err;
 
 err:
-	mutex_unlock(&s->v4l2_lock);
+	mutex_unlock(&dev->v4l2_lock);
 
 	return ret;
 }
 
 static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
 {
-	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_usb_device *d = pdata->dvb_usb_device;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
-	mutex_lock(&s->v4l2_lock);
+	mutex_lock(&dev->v4l2_lock);
 
-	rtl2832_sdr_kill_urbs(s);
-	rtl2832_sdr_free_urbs(s);
-	rtl2832_sdr_free_stream_bufs(s);
-	rtl2832_sdr_cleanup_queued_bufs(s);
-	rtl2832_sdr_unset_adc(s);
-	rtl2832_sdr_unset_tuner(s);
+	rtl2832_sdr_kill_urbs(dev);
+	rtl2832_sdr_free_urbs(dev);
+	rtl2832_sdr_free_stream_bufs(dev);
+	rtl2832_sdr_cleanup_queued_bufs(dev);
+	rtl2832_sdr_unset_adc(dev);
+	rtl2832_sdr_unset_tuner(dev);
 
-	clear_bit(POWER_ON, &s->flags);
+	clear_bit(POWER_ON, &dev->flags);
 
 	/* disable ADC */
-	if (s->d->props->frontend_ctrl)
-		s->d->props->frontend_ctrl(s->fe, 0);
+	if (d->props->frontend_ctrl)
+		d->props->frontend_ctrl(pdata->dvb_frontend, 0);
 
-	if (s->d->props->power_ctrl)
-		s->d->props->power_ctrl(s->d, 0);
+	if (d->props->power_ctrl)
+		d->props->power_ctrl(d, 0);
 
-	mutex_unlock(&s->v4l2_lock);
+	mutex_unlock(&dev->v4l2_lock);
 }
 
 static struct vb2_ops rtl2832_sdr_vb2_ops = {
@@ -1091,9 +966,10 @@ static struct vb2_ops rtl2832_sdr_vb2_ops = {
 static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
 		struct v4l2_tuner *v)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "index=%d type=%d\n", v->index, v->type);
+	dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type);
 
 	if (v->index == 0) {
 		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name));
@@ -1117,9 +993,10 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
 static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
 		const struct v4l2_tuner *v)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
 	if (v->index > 1)
 		return -EINVAL;
@@ -1129,10 +1006,11 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
 static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
 		struct v4l2_frequency_band *band)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "tuner=%d type=%d index=%d\n",
-			band->tuner, band->type, band->index);
+	dev_dbg(&pdev->dev, "tuner=%d type=%d index=%d\n",
+		band->tuner, band->type, band->index);
 
 	if (band->tuner == 0) {
 		if (band->index >= ARRAY_SIZE(bands_adc))
@@ -1154,17 +1032,17 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
 static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
 		struct v4l2_frequency *f)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 	int ret  = 0;
 
-	dev_dbg(&s->udev->dev, "tuner=%d type=%d\n",
-			f->tuner, f->type);
+	dev_dbg(&pdev->dev, "tuner=%d type=%d\n", f->tuner, f->type);
 
 	if (f->tuner == 0) {
-		f->frequency = s->f_adc;
+		f->frequency = dev->f_adc;
 		f->type = V4L2_TUNER_ADC;
 	} else if (f->tuner == 1) {
-		f->frequency = s->f_tuner;
+		f->frequency = dev->f_tuner;
 		f->type = V4L2_TUNER_RF;
 	} else {
 		return -EINVAL;
@@ -1176,11 +1054,12 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
 static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 		const struct v4l2_frequency *f)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 	int ret, band;
 
-	dev_dbg(&s->udev->dev, "tuner=%d type=%d frequency=%u\n",
-			f->tuner, f->type, f->frequency);
+	dev_dbg(&pdev->dev, "tuner=%d type=%d frequency=%u\n",
+		f->tuner, f->type, f->frequency);
 
 	/* ADC band midpoints */
 	#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2)
@@ -1194,19 +1073,19 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 		else
 			band = 2;
 
-		s->f_adc = clamp_t(unsigned int, f->frequency,
+		dev->f_adc = clamp_t(unsigned int, f->frequency,
 				bands_adc[band].rangelow,
 				bands_adc[band].rangehigh);
 
-		dev_dbg(&s->udev->dev, "ADC frequency=%u Hz\n", s->f_adc);
-		ret = rtl2832_sdr_set_adc(s);
+		dev_dbg(&pdev->dev, "ADC frequency=%u Hz\n", dev->f_adc);
+		ret = rtl2832_sdr_set_adc(dev);
 	} else if (f->tuner == 1) {
-		s->f_tuner = clamp_t(unsigned int, f->frequency,
+		dev->f_tuner = clamp_t(unsigned int, f->frequency,
 				bands_fm[0].rangelow,
 				bands_fm[0].rangehigh);
-		dev_dbg(&s->udev->dev, "RF frequency=%u Hz\n", f->frequency);
+		dev_dbg(&pdev->dev, "RF frequency=%u Hz\n", f->frequency);
 
-		ret = rtl2832_sdr_set_tuner_freq(s);
+		ret = rtl2832_sdr_set_tuner_freq(dev);
 	} else {
 		ret = -EINVAL;
 	}
@@ -1217,11 +1096,12 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv,
 static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_fmtdesc *f)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
-	if (f->index >= s->num_formats)
+	if (f->index >= dev->num_formats)
 		return -EINVAL;
 
 	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
@@ -1233,12 +1113,13 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
 static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 
-	dev_dbg(&s->udev->dev, "\n");
+	dev_dbg(&pdev->dev, "\n");
 
-	f->fmt.sdr.pixelformat = s->pixelformat;
-	f->fmt.sdr.buffersize = s->buffersize;
+	f->fmt.sdr.pixelformat = dev->pixelformat;
+	f->fmt.sdr.buffersize = dev->buffersize;
 
 	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
 
@@ -1248,28 +1129,29 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
 static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
-	struct vb2_queue *q = &s->vb_queue;
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
+	struct vb2_queue *q = &dev->vb_queue;
 	int i;
 
-	dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n",
-			(char *)&f->fmt.sdr.pixelformat);
+	dev_dbg(&pdev->dev, "pixelformat fourcc %4.4s\n",
+		(char *)&f->fmt.sdr.pixelformat);
 
 	if (vb2_is_busy(q))
 		return -EBUSY;
 
 	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	for (i = 0; i < s->num_formats; i++) {
+	for (i = 0; i < dev->num_formats; i++) {
 		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
-			s->pixelformat = formats[i].pixelformat;
-			s->buffersize = formats[i].buffersize;
+			dev->pixelformat = formats[i].pixelformat;
+			dev->buffersize = formats[i].buffersize;
 			f->fmt.sdr.buffersize = formats[i].buffersize;
 			return 0;
 		}
 	}
 
-	s->pixelformat = formats[0].pixelformat;
-	s->buffersize = formats[0].buffersize;
+	dev->pixelformat = formats[0].pixelformat;
+	dev->buffersize = formats[0].buffersize;
 	f->fmt.sdr.pixelformat = formats[0].pixelformat;
 	f->fmt.sdr.buffersize = formats[0].buffersize;
 
@@ -1279,14 +1161,15 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
 static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
 		struct v4l2_format *f)
 {
-	struct rtl2832_sdr_state *s = video_drvdata(file);
+	struct rtl2832_sdr_dev *dev = video_drvdata(file);
+	struct platform_device *pdev = dev->pdev;
 	int i;
 
-	dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n",
-			(char *)&f->fmt.sdr.pixelformat);
+	dev_dbg(&pdev->dev, "pixelformat fourcc %4.4s\n",
+		(char *)&f->fmt.sdr.pixelformat);
 
 	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
-	for (i = 0; i < s->num_formats; i++) {
+	for (i = 0; i < dev->num_formats; i++) {
 		if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
 			f->fmt.sdr.buffersize = formats[i].buffersize;
 			return 0;
@@ -1348,37 +1231,38 @@ static struct video_device rtl2832_sdr_template = {
 
 static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct rtl2832_sdr_state *s =
-			container_of(ctrl->handler, struct rtl2832_sdr_state,
+	struct rtl2832_sdr_dev *dev =
+			container_of(ctrl->handler, struct rtl2832_sdr_dev,
 					hdl);
-	struct dvb_frontend *fe = s->fe;
+	struct platform_device *pdev = dev->pdev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
+	struct dvb_frontend *fe = pdata->dvb_frontend;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 
-	dev_dbg(&s->udev->dev,
-			"id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
-			ctrl->id, ctrl->name, ctrl->val,
-			ctrl->minimum, ctrl->maximum, ctrl->step);
+	dev_dbg(&pdev->dev, "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
+		ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum,
+		ctrl->step);
 
 	switch (ctrl->id) {
 	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
 	case V4L2_CID_RF_TUNER_BANDWIDTH:
 		/* TODO: these controls should be moved to tuner drivers */
-		if (s->bandwidth_auto->val) {
+		if (dev->bandwidth_auto->val) {
 			/* Round towards the closest legal value */
-			s32 val = s->f_adc + div_u64(s->bandwidth->step, 2);
+			s32 val = dev->f_adc + div_u64(dev->bandwidth->step, 2);
 			u32 offset;
 
-			val = clamp_t(s32, val, s->bandwidth->minimum,
-				      s->bandwidth->maximum);
-			offset = val - s->bandwidth->minimum;
-			offset = s->bandwidth->step *
-				div_u64(offset, s->bandwidth->step);
-			s->bandwidth->val = s->bandwidth->minimum + offset;
+			val = clamp_t(s32, val, dev->bandwidth->minimum,
+				      dev->bandwidth->maximum);
+			offset = val - dev->bandwidth->minimum;
+			offset = dev->bandwidth->step *
+				div_u64(offset, dev->bandwidth->step);
+			dev->bandwidth->val = dev->bandwidth->minimum + offset;
 		}
-		c->bandwidth_hz = s->bandwidth->val;
+		c->bandwidth_hz = dev->bandwidth->val;
 
-		if (!test_bit(POWER_ON, &s->flags))
+		if (!test_bit(POWER_ON, &dev->flags))
 			return 0;
 
 		if (fe->ops.tuner_ops.set_params)
@@ -1399,154 +1283,195 @@ static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = {
 
 static void rtl2832_sdr_video_release(struct v4l2_device *v)
 {
-	struct rtl2832_sdr_state *s =
-			container_of(v, struct rtl2832_sdr_state, v4l2_dev);
+	struct rtl2832_sdr_dev *dev =
+			container_of(v, struct rtl2832_sdr_dev, v4l2_dev);
+	struct platform_device *pdev = dev->pdev;
+
+	dev_dbg(&pdev->dev, "\n");
 
-	v4l2_ctrl_handler_free(&s->hdl);
-	v4l2_device_unregister(&s->v4l2_dev);
-	kfree(s);
+	v4l2_ctrl_handler_free(&dev->hdl);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	kfree(dev);
 }
 
-struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
-		struct v4l2_subdev *sd)
+/* Platform driver interface */
+static int rtl2832_sdr_probe(struct platform_device *pdev)
 {
-	int ret;
-	struct rtl2832_sdr_state *s;
+	struct rtl2832_sdr_dev *dev;
+	struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
 	const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops;
-	struct dvb_usb_device *d = i2c_get_adapdata(i2c);
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	dev_dbg(&pdev->dev, "\n");
 
-	s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL);
-	if (s == NULL) {
-		dev_err(&d->udev->dev,
-				"Could not allocate memory for rtl2832_sdr_state\n");
-		return NULL;
+	if (!pdata) {
+		dev_err(&pdev->dev, "Cannot proceed without platform data\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	if (!pdev->dev.parent->driver) {
+		dev_dbg(&pdev->dev, "No parent device\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	/* try to refcount host drv since we are the consumer */
+	if (!try_module_get(pdev->dev.parent->driver->owner)) {
+		dev_err(&pdev->dev, "Refcount fail");
+		ret = -EINVAL;
+		goto err;
+	}
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		ret = -ENOMEM;
+		goto err_module_put;
 	}
 
 	/* setup the state */
-	s->fe = fe;
-	s->d = d;
-	s->udev = d->udev;
-	s->i2c = i2c;
-	s->cfg = cfg;
-	s->f_adc = bands_adc[0].rangelow;
-	s->f_tuner = bands_fm[0].rangelow;
-	s->pixelformat = formats[0].pixelformat;
-	s->buffersize = formats[0].buffersize;
-	s->num_formats = NUM_FORMATS;
+	subdev = pdata->v4l2_subdev;
+	dev->pdev = pdev;
+	dev->udev = pdata->dvb_usb_device->udev;
+	dev->f_adc = bands_adc[0].rangelow;
+	dev->f_tuner = bands_fm[0].rangelow;
+	dev->pixelformat = formats[0].pixelformat;
+	dev->buffersize = formats[0].buffersize;
+	dev->num_formats = NUM_FORMATS;
 	if (!rtl2832_sdr_emulated_fmt)
-		s->num_formats -= 1;
+		dev->num_formats -= 1;
 
-	mutex_init(&s->v4l2_lock);
-	mutex_init(&s->vb_queue_lock);
-	spin_lock_init(&s->queued_bufs_lock);
-	INIT_LIST_HEAD(&s->queued_bufs);
+	mutex_init(&dev->v4l2_lock);
+	mutex_init(&dev->vb_queue_lock);
+	spin_lock_init(&dev->queued_bufs_lock);
+	INIT_LIST_HEAD(&dev->queued_bufs);
 
 	/* Init videobuf2 queue structure */
-	s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
-	s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	s->vb_queue.drv_priv = s;
-	s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf);
-	s->vb_queue.ops = &rtl2832_sdr_vb2_ops;
-	s->vb_queue.mem_ops = &vb2_vmalloc_memops;
-	s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	ret = vb2_queue_init(&s->vb_queue);
+	dev->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+	dev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	dev->vb_queue.drv_priv = dev;
+	dev->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf);
+	dev->vb_queue.ops = &rtl2832_sdr_vb2_ops;
+	dev->vb_queue.mem_ops = &vb2_vmalloc_memops;
+	dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	ret = vb2_queue_init(&dev->vb_queue);
 	if (ret) {
-		dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
-		goto err_free_mem;
+		dev_err(&pdev->dev, "Could not initialize vb2 queue\n");
+		goto err_kfree;
 	}
 
 	/* Register controls */
-	switch (s->cfg->tuner) {
-	case RTL2832_TUNER_E4000:
-		v4l2_ctrl_handler_init(&s->hdl, 9);
-		if (sd)
-			v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL);
+	switch (pdata->tuner) {
+	case RTL2832_SDR_TUNER_E4000:
+		v4l2_ctrl_handler_init(&dev->hdl, 9);
+		if (subdev)
+			v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler, NULL);
 		break;
-	case RTL2832_TUNER_R820T:
-		v4l2_ctrl_handler_init(&s->hdl, 2);
-		s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
-						      V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
-						      0, 1, 1, 1);
-		s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
-						 V4L2_CID_RF_TUNER_BANDWIDTH,
-						 0, 8000000, 100000, 0);
-		v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+	case RTL2832_SDR_TUNER_R820T:
+	case RTL2832_SDR_TUNER_R828D:
+		v4l2_ctrl_handler_init(&dev->hdl, 2);
+		dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, ops,
+							V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+							0, 1, 1, 1);
+		dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, ops,
+						   V4L2_CID_RF_TUNER_BANDWIDTH,
+						   0, 8000000, 100000, 0);
+		v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
 		break;
-	case RTL2832_TUNER_FC0012:
-	case RTL2832_TUNER_FC0013:
-		v4l2_ctrl_handler_init(&s->hdl, 2);
-		s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
-						      V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
-						      0, 1, 1, 1);
-		s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
-						 V4L2_CID_RF_TUNER_BANDWIDTH,
-						 6000000, 8000000, 1000000,
-						 6000000);
-		v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
+	case RTL2832_SDR_TUNER_FC0012:
+	case RTL2832_SDR_TUNER_FC0013:
+		v4l2_ctrl_handler_init(&dev->hdl, 2);
+		dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, ops,
+							V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+							0, 1, 1, 1);
+		dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, ops,
+						   V4L2_CID_RF_TUNER_BANDWIDTH,
+						   6000000, 8000000, 1000000,
+						   6000000);
+		v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
 		break;
 	default:
-		v4l2_ctrl_handler_init(&s->hdl, 0);
-		dev_notice(&s->udev->dev, "%s: Unsupported tuner\n",
-				KBUILD_MODNAME);
-		goto err_free_controls;
+		v4l2_ctrl_handler_init(&dev->hdl, 0);
+		dev_err(&pdev->dev, "Unsupported tuner\n");
+		goto err_v4l2_ctrl_handler_free;
 	}
-
-	if (s->hdl.error) {
-		ret = s->hdl.error;
-		dev_err(&s->udev->dev, "Could not initialize controls\n");
-		goto err_free_controls;
+	if (dev->hdl.error) {
+		ret = dev->hdl.error;
+		dev_err(&pdev->dev, "Could not initialize controls\n");
+		goto err_v4l2_ctrl_handler_free;
 	}
 
 	/* Init video_device structure */
-	s->vdev = rtl2832_sdr_template;
-	s->vdev.queue = &s->vb_queue;
-	s->vdev.queue->lock = &s->vb_queue_lock;
-	video_set_drvdata(&s->vdev, s);
+	dev->vdev = rtl2832_sdr_template;
+	dev->vdev.queue = &dev->vb_queue;
+	dev->vdev.queue->lock = &dev->vb_queue_lock;
+	video_set_drvdata(&dev->vdev, dev);
 
 	/* Register the v4l2_device structure */
-	s->v4l2_dev.release = rtl2832_sdr_video_release;
-	ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev);
+	dev->v4l2_dev.release = rtl2832_sdr_video_release;
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register v4l2-device (%d)\n", ret);
-		goto err_free_controls;
+		dev_err(&pdev->dev, "Failed to register v4l2-device %d\n", ret);
+		goto err_v4l2_ctrl_handler_free;
 	}
 
-	s->v4l2_dev.ctrl_handler = &s->hdl;
-	s->vdev.v4l2_dev = &s->v4l2_dev;
-	s->vdev.lock = &s->v4l2_lock;
-	s->vdev.vfl_dir = VFL_DIR_RX;
+	dev->v4l2_dev.ctrl_handler = &dev->hdl;
+	dev->vdev.v4l2_dev = &dev->v4l2_dev;
+	dev->vdev.lock = &dev->v4l2_lock;
+	dev->vdev.vfl_dir = VFL_DIR_RX;
 
-	ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+	ret = video_register_device(&dev->vdev, VFL_TYPE_SDR, -1);
 	if (ret) {
-		dev_err(&s->udev->dev,
-				"Failed to register as video device (%d)\n",
-				ret);
-		goto err_unregister_v4l2_dev;
+		dev_err(&pdev->dev, "Failed to register as video device %d\n",
+			ret);
+		goto err_v4l2_device_unregister;
 	}
-	dev_info(&s->udev->dev, "Registered as %s\n",
-			video_device_node_name(&s->vdev));
-
-	fe->sec_priv = s;
-	fe->ops.release_sec = rtl2832_sdr_release_sec;
-
-	dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n",
-			KBUILD_MODNAME);
-	dev_notice(&s->udev->dev,
-			"%s: SDR API is still slightly experimental and functionality changes may follow\n",
-			KBUILD_MODNAME);
-	return fe;
-
-err_unregister_v4l2_dev:
-	v4l2_device_unregister(&s->v4l2_dev);
-err_free_controls:
-	v4l2_ctrl_handler_free(&s->hdl);
-err_free_mem:
-	kfree(s);
-	return NULL;
+	dev_info(&pdev->dev, "Registered as %s\n",
+		 video_device_node_name(&dev->vdev));
+	dev_info(&pdev->dev, "Realtek RTL2832 SDR attached\n");
+	dev_notice(&pdev->dev,
+		   "SDR API is still slightly experimental and functionality changes may follow\n");
+	platform_set_drvdata(pdev, dev);
+	return 0;
+err_v4l2_device_unregister:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_v4l2_ctrl_handler_free:
+	v4l2_ctrl_handler_free(&dev->hdl);
+err_kfree:
+	kfree(dev);
+err_module_put:
+	module_put(pdev->dev.parent->driver->owner);
+err:
+	return ret;
 }
-EXPORT_SYMBOL(rtl2832_sdr_attach);
+
+static int rtl2832_sdr_remove(struct platform_device *pdev)
+{
+	struct rtl2832_sdr_dev *dev = platform_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "\n");
+
+	mutex_lock(&dev->vb_queue_lock);
+	mutex_lock(&dev->v4l2_lock);
+	/* No need to keep the urbs around after disconnection */
+	dev->udev = NULL;
+	v4l2_device_disconnect(&dev->v4l2_dev);
+	video_unregister_device(&dev->vdev);
+	mutex_unlock(&dev->v4l2_lock);
+	mutex_unlock(&dev->vb_queue_lock);
+	v4l2_device_put(&dev->v4l2_dev);
+	module_put(pdev->dev.parent->driver->owner);
+
+	return 0;
+}
+
+static struct platform_driver rtl2832_sdr_driver = {
+	.driver = {
+		.name   = "rtl2832_sdr",
+		.owner  = THIS_MODULE,
+	},
+	.probe          = rtl2832_sdr_probe,
+	.remove         = rtl2832_sdr_remove,
+};
+module_platform_driver(rtl2832_sdr_driver);
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Realtek RTL2832 SDR driver");
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h
index b865fadf184f..d2594768bff2 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.h
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.h
@@ -20,35 +20,48 @@
  * GNU Radio plugin "gr-kernel" for device usage will be on:
  * http://git.linuxtv.org/anttip/gr-kernel.git
  *
- * TODO:
- * Help is very highly welcome for these + all the others you could imagine:
- * - move controls to V4L2 API
- * - use libv4l2 for stream format conversions
- * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
- * - SDRSharp support
  */
 
 #ifndef RTL2832_SDR_H
 #define RTL2832_SDR_H
 
-#include <linux/kconfig.h>
+#include <linux/i2c.h>
 #include <media/v4l2-subdev.h>
+#include "dvb_frontend.h"
 
-/* for config struct */
-#include "rtl2832.h"
+/**
+ * struct rtl2832_sdr_platform_data - Platform data for the rtl2832_sdr driver
+ * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
+ * @tuner: Used tuner model.
+ * @i2c_client: rtl2832 demod driver I2C client.
+ * @bulk_read: rtl2832 driver private I/O interface.
+ * @bulk_write: rtl2832 driver private I/O interface.
+ * @update_bits: rtl2832 driver private I/O interface.
+ * @dvb_frontend: rtl2832 DVB frontend.
+ * @v4l2_subdev: Tuner v4l2 controls.
+ * @dvb_usb_device: DVB USB interface for USB streaming.
+ */
+
+struct rtl2832_sdr_platform_data {
+	u32 clk;
+	/*
+	 * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
+	 */
+#define RTL2832_SDR_TUNER_TUA9001   0x24
+#define RTL2832_SDR_TUNER_FC0012    0x26
+#define RTL2832_SDR_TUNER_E4000     0x27
+#define RTL2832_SDR_TUNER_FC0013    0x29
+#define RTL2832_SDR_TUNER_R820T     0x2a
+#define RTL2832_SDR_TUNER_R828D     0x2b
+	u8 tuner;
 
-#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
-extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
-	struct v4l2_subdev *sd);
-#else
-static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
-	struct v4l2_subdev *sd)
-{
-	dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
+	struct i2c_client *i2c_client;
+	int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t);
+	int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t);
+	int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int);
+	struct dvb_frontend *dvb_frontend;
+	struct v4l2_subdev *v4l2_subdev;
+	struct dvb_usb_device *dvb_usb_device;
+};
 
 #endif /* RTL2832_SDR_H */
diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c
index f71b06221e14..5ff474a7ff29 100644
--- a/drivers/media/dvb-frontends/s5h1409.c
+++ b/drivers/media/dvb-frontends/s5h1409.c
@@ -1021,9 +1021,3 @@ static struct dvb_frontend_ops s5h1409_ops = {
 MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb-frontends/s5h1409.h b/drivers/media/dvb-frontends/s5h1409.h
index 63b1e0a34e4e..9e143f5c8107 100644
--- a/drivers/media/dvb-frontends/s5h1409.h
+++ b/drivers/media/dvb-frontends/s5h1409.h
@@ -81,8 +81,3 @@ static inline struct dvb_frontend *s5h1409_attach(
 #endif /* CONFIG_DVB_S5H1409 */
 
 #endif /* __S5H1409_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c
index 6cc4b7a9dd60..64f35fed7ae1 100644
--- a/drivers/media/dvb-frontends/s5h1411.c
+++ b/drivers/media/dvb-frontends/s5h1411.c
@@ -944,8 +944,3 @@ MODULE_PARM_DESC(debug, "Enable verbose debug messages");
 MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb-frontends/s5h1411.h b/drivers/media/dvb-frontends/s5h1411.h
index e4f56871f982..1d7deb615674 100644
--- a/drivers/media/dvb-frontends/s5h1411.h
+++ b/drivers/media/dvb-frontends/s5h1411.h
@@ -83,8 +83,3 @@ static inline struct dvb_frontend *s5h1411_attach(
 #endif /* CONFIG_DVB_S5H1411 */
 
 #endif /* __S5H1411_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index ce9ab442b4b6..5db588ebfc24 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -19,16 +19,17 @@
 static const struct dvb_frontend_ops si2168_ops;
 
 /* execute firmware command */
-static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
 {
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	int ret;
 	unsigned long timeout;
 
-	mutex_lock(&s->i2c_mutex);
+	mutex_lock(&dev->i2c_mutex);
 
 	if (cmd->wlen) {
 		/* write cmd and args for firmware */
-		ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
+		ret = i2c_master_send(client, cmd->args, cmd->wlen);
 		if (ret < 0) {
 			goto err_mutex_unlock;
 		} else if (ret != cmd->wlen) {
@@ -39,10 +40,10 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
 
 	if (cmd->rlen) {
 		/* wait cmd execution terminate */
-		#define TIMEOUT 50
+		#define TIMEOUT 70
 		timeout = jiffies + msecs_to_jiffies(TIMEOUT);
 		while (!time_after(jiffies, timeout)) {
-			ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
+			ret = i2c_master_recv(client, cmd->args, cmd->rlen);
 			if (ret < 0) {
 				goto err_mutex_unlock;
 			} else if (ret != cmd->rlen) {
@@ -55,7 +56,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
 				break;
 		}
 
-		dev_dbg(&s->client->dev, "cmd execution took %d ms\n",
+		dev_dbg(&client->dev, "cmd execution took %d ms\n",
 				jiffies_to_msecs(jiffies) -
 				(jiffies_to_msecs(timeout) - TIMEOUT));
 
@@ -65,29 +66,26 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
 		}
 	}
 
-	ret = 0;
+	mutex_unlock(&dev->i2c_mutex);
+	return 0;
 
 err_mutex_unlock:
-	mutex_unlock(&s->i2c_mutex);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	mutex_unlock(&dev->i2c_mutex);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-	struct si2168 *s = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 	struct si2168_cmd cmd;
 
 	*status = 0;
 
-	if (!s->active) {
+	if (!dev->active) {
 		ret = -EAGAIN;
 		goto err;
 	}
@@ -113,21 +111,10 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
 		goto err;
 	}
 
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	/*
-	 * Possible values seen, in order from strong signal to weak:
-	 * 16 0001 0110 full lock
-	 * 1e 0001 1110 partial lock
-	 * 1a 0001 1010 partial lock
-	 * 18 0001 1000 no lock
-	 *
-	 * [b3:b1] lock bits
-	 * [b4] statistics ready? Set in a few secs after lock is gained.
-	 */
-
 	switch ((cmd.args[2] >> 1) & 0x03) {
 	case 0x01:
 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
@@ -138,7 +125,7 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
 		break;
 	}
 
-	s->fe_status = *status;
+	dev->fe_status = *status;
 
 	if (*status & FE_HAS_LOCK) {
 		c->cnr.len = 1;
@@ -149,30 +136,31 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 	}
 
-	dev_dbg(&s->client->dev, "status=%02x args=%*ph\n",
+	dev_dbg(&client->dev, "status=%02x args=%*ph\n",
 			*status, cmd.rlen, cmd.args);
 
 	return 0;
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2168_set_frontend(struct dvb_frontend *fe)
 {
-	struct si2168 *s = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 	struct si2168_cmd cmd;
 	u8 bandwidth, delivery_system;
 
-	dev_dbg(&s->client->dev,
-			"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n",
-			c->delivery_system, c->modulation,
-			c->frequency, c->bandwidth_hz, c->symbol_rate,
-			c->inversion, c->stream_id);
+	dev_dbg(&client->dev,
+			"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%u\n",
+			c->delivery_system, c->modulation, c->frequency,
+			c->bandwidth_hz, c->symbol_rate, c->inversion,
+			c->stream_id);
 
-	if (!s->active) {
+	if (!dev->active) {
 		ret = -EAGAIN;
 		goto err;
 	}
@@ -192,7 +180,12 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	if (c->bandwidth_hz <= 5000000)
+	if (c->bandwidth_hz == 0) {
+		ret = -EINVAL;
+		goto err;
+	} else if (c->bandwidth_hz <= 2000000)
+		bandwidth = 0x02;
+	else if (c->bandwidth_hz <= 5000000)
 		bandwidth = 0x05;
 	else if (c->bandwidth_hz <= 6000000)
 		bandwidth = 0x06;
@@ -217,7 +210,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
 	cmd.wlen = 5;
 	cmd.rlen = 5;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -230,7 +223,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 		memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 3;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -241,7 +234,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 		cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
 		cmd.wlen = 3;
 		cmd.rlen = 1;
-		ret = si2168_cmd_execute(s, &cmd);
+		ret = si2168_cmd_execute(client, &cmd);
 		if (ret)
 			goto err;
 	}
@@ -249,35 +242,35 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\x51\x03", 2);
 	cmd.wlen = 2;
 	cmd.rlen = 12;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x12\x08\x04", 3);
 	cmd.wlen = 3;
 	cmd.rlen = 3;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -285,18 +278,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 	cmd.args[4] = delivery_system | bandwidth;
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	/* set DVB-C symbol rate */
 	if (c->delivery_system == SYS_DVBC_ANNEX_A) {
 		memcpy(cmd.args, "\x14\x00\x02\x11", 4);
-		cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
+		cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff;
 		cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
 		cmd.wlen = 6;
 		cmd.rlen = 4;
-		ret = si2168_cmd_execute(s, &cmd);
+		ret = si2168_cmd_execute(client, &cmd);
 		if (ret)
 			goto err;
 	}
@@ -304,88 +297,88 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6);
-	cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
+	cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6);
-	cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
+	cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	memcpy(cmd.args, "\x85", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	s->delivery_system = c->delivery_system;
+	dev->delivery_system = c->delivery_system;
 
 	return 0;
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2168_init(struct dvb_frontend *fe)
 {
-	struct si2168 *s = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	int ret, len, remaining;
-	const struct firmware *fw = NULL;
-	u8 *fw_file;
-	const unsigned int i2c_wr_max = 8;
+	const struct firmware *fw;
+	const char *fw_name;
 	struct si2168_cmd cmd;
 	unsigned int chip_id;
 
-	dev_dbg(&s->client->dev, "\n");
+	dev_dbg(&client->dev, "\n");
 
 	/* initialize */
 	memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
 	cmd.wlen = 13;
 	cmd.rlen = 0;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	if (s->fw_loaded) {
+	if (dev->fw_loaded) {
 		/* resume */
 		memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
 		cmd.wlen = 8;
 		cmd.rlen = 1;
-		ret = si2168_cmd_execute(s, &cmd);
+		ret = si2168_cmd_execute(client, &cmd);
 		if (ret)
 			goto err;
 
 		memcpy(cmd.args, "\x85", 1);
 		cmd.wlen = 1;
 		cmd.rlen = 1;
-		ret = si2168_cmd_execute(s, &cmd);
+		ret = si2168_cmd_execute(client, &cmd);
 		if (ret)
 			goto err;
 
@@ -396,7 +389,7 @@ static int si2168_init(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
 	cmd.wlen = 8;
 	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -404,7 +397,7 @@ static int si2168_init(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\x02", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 13;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -417,50 +410,48 @@ static int si2168_init(struct dvb_frontend *fe)
 
 	switch (chip_id) {
 	case SI2168_A20:
-		fw_file = SI2168_A20_FIRMWARE;
+		fw_name = SI2168_A20_FIRMWARE;
 		break;
 	case SI2168_A30:
-		fw_file = SI2168_A30_FIRMWARE;
+		fw_name = SI2168_A30_FIRMWARE;
 		break;
 	case SI2168_B40:
-		fw_file = SI2168_B40_FIRMWARE;
+		fw_name = SI2168_B40_FIRMWARE;
 		break;
 	default:
-		dev_err(&s->client->dev,
-				"unknown chip version Si21%d-%c%c%c\n",
+		dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
 				cmd.args[2], cmd.args[1],
 				cmd.args[3], cmd.args[4]);
 		ret = -EINVAL;
 		goto err;
 	}
 
-	/* cold state - try to download firmware */
-	dev_info(&s->client->dev, "found a '%s' in cold state\n",
-			si2168_ops.info.name);
+	dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
+			cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
 
 	/* request the firmware, this will block and timeout */
-	ret = request_firmware(&fw, fw_file, &s->client->dev);
+	ret = request_firmware(&fw, fw_name, &client->dev);
 	if (ret) {
 		/* fallback mechanism to handle old name for Si2168 B40 fw */
 		if (chip_id == SI2168_B40) {
-			fw_file = SI2168_B40_FIRMWARE_FALLBACK;
-			ret = request_firmware(&fw, fw_file, &s->client->dev);
+			fw_name = SI2168_B40_FIRMWARE_FALLBACK;
+			ret = request_firmware(&fw, fw_name, &client->dev);
 		}
 
 		if (ret == 0) {
-			dev_notice(&s->client->dev,
+			dev_notice(&client->dev,
 					"please install firmware file '%s'\n",
 					SI2168_B40_FIRMWARE);
 		} else {
-			dev_err(&s->client->dev,
+			dev_err(&client->dev,
 					"firmware file '%s' not found\n",
-					fw_file);
-			goto error_fw_release;
+					fw_name);
+			goto err_release_firmware;
 		}
 	}
 
-	dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
-			fw_file);
+	dev_info(&client->dev, "downloading firmware from file '%s'\n",
+			fw_name);
 
 	if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
 		/* firmware is in the new format */
@@ -469,41 +460,37 @@ static int si2168_init(struct dvb_frontend *fe)
 			memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
 			cmd.wlen = len;
 			cmd.rlen = 1;
-			ret = si2168_cmd_execute(s, &cmd);
-			if (ret) {
-				dev_err(&s->client->dev,
-						"firmware download failed=%d\n",
-						ret);
-				goto error_fw_release;
-			}
+			ret = si2168_cmd_execute(client, &cmd);
+			if (ret)
+				break;
 		}
-	} else {
+	} else if (fw->size % 8 == 0) {
 		/* firmware is in the old format */
-		for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
-			len = remaining;
-			if (len > i2c_wr_max)
-				len = i2c_wr_max;
-
+		for (remaining = fw->size; remaining > 0; remaining -= 8) {
+			len = 8;
 			memcpy(cmd.args, &fw->data[fw->size - remaining], len);
 			cmd.wlen = len;
 			cmd.rlen = 1;
-			ret = si2168_cmd_execute(s, &cmd);
-			if (ret) {
-				dev_err(&s->client->dev,
-						"firmware download failed=%d\n",
-						ret);
-				goto error_fw_release;
-			}
+			ret = si2168_cmd_execute(client, &cmd);
+			if (ret)
+				break;
 		}
+	} else {
+		/* bad or unknown firmware format */
+		ret = -EINVAL;
+	}
+
+	if (ret) {
+		dev_err(&client->dev, "firmware download failed %d\n", ret);
+		goto err_release_firmware;
 	}
 
 	release_firmware(fw);
-	fw = NULL;
 
 	memcpy(cmd.args, "\x01\x01", 2);
 	cmd.wlen = 2;
 	cmd.rlen = 1;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -511,58 +498,56 @@ static int si2168_init(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\x11", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 10;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	dev_dbg(&s->client->dev, "firmware version: %c.%c.%d\n",
+	dev_info(&client->dev, "firmware version: %c.%c.%d\n",
 			cmd.args[6], cmd.args[7], cmd.args[8]);
 
 	/* set ts mode */
 	memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
-	cmd.args[4] |= s->ts_mode;
+	cmd.args[4] |= dev->ts_mode;
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	s->fw_loaded = true;
-
-	dev_info(&s->client->dev, "found a '%s' in warm state\n",
-			si2168_ops.info.name);
+	dev->fw_loaded = true;
 warm:
-	s->active = true;
+	dev->active = true;
 
 	return 0;
 
-error_fw_release:
+err_release_firmware:
 	release_firmware(fw);
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2168_sleep(struct dvb_frontend *fe)
 {
-	struct si2168 *s = fe->demodulator_priv;
+	struct i2c_client *client = fe->demodulator_priv;
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	int ret;
 	struct si2168_cmd cmd;
 
-	dev_dbg(&s->client->dev, "\n");
+	dev_dbg(&client->dev, "\n");
 
-	s->active = false;
+	dev->active = false;
 
 	memcpy(cmd.args, "\x13", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 0;
-	ret = si2168_cmd_execute(s, &cmd);
+	ret = si2168_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	return 0;
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -581,21 +566,22 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe,
  */
 static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
 {
-	struct si2168 *s = mux_priv;
+	struct i2c_client *client = mux_priv;
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	int ret;
 	struct i2c_msg gate_open_msg = {
-		.addr = s->client->addr,
+		.addr = client->addr,
 		.flags = 0,
 		.len = 3,
 		.buf = "\xc0\x0d\x01",
 	};
 
-	mutex_lock(&s->i2c_mutex);
+	mutex_lock(&dev->i2c_mutex);
 
 	/* open tuner I2C gate */
-	ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1);
+	ret = __i2c_transfer(client->adapter, &gate_open_msg, 1);
 	if (ret != 1) {
-		dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
+		dev_warn(&client->dev, "i2c write failed=%d\n", ret);
 		if (ret >= 0)
 			ret = -EREMOTEIO;
 	} else {
@@ -607,26 +593,27 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
 
 static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
 {
-	struct si2168 *s = mux_priv;
+	struct i2c_client *client = mux_priv;
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 	int ret;
 	struct i2c_msg gate_close_msg = {
-		.addr = s->client->addr,
+		.addr = client->addr,
 		.flags = 0,
 		.len = 3,
 		.buf = "\xc0\x0d\x00",
 	};
 
 	/* close tuner I2C gate */
-	ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1);
+	ret = __i2c_transfer(client->adapter, &gate_close_msg, 1);
 	if (ret != 1) {
-		dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
+		dev_warn(&client->dev, "i2c write failed=%d\n", ret);
 		if (ret >= 0)
 			ret = -EREMOTEIO;
 	} else {
 		ret = 0;
 	}
 
-	mutex_unlock(&s->i2c_mutex);
+	mutex_unlock(&dev->i2c_mutex);
 
 	return ret;
 }
@@ -635,6 +622,8 @@ static const struct dvb_frontend_ops si2168_ops = {
 	.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
 	.info = {
 		.name = "Silicon Labs Si2168",
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 7200000,
 		.caps =	FE_CAN_FEC_1_2 |
 			FE_CAN_FEC_2_3 |
 			FE_CAN_FEC_3_4 |
@@ -670,71 +659,69 @@ static int si2168_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct si2168_config *config = client->dev.platform_data;
-	struct si2168 *s;
+	struct si2168_dev *dev;
 	int ret;
 
 	dev_dbg(&client->dev, "\n");
 
-	s = kzalloc(sizeof(struct si2168), GFP_KERNEL);
-	if (!s) {
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
 		ret = -ENOMEM;
 		dev_err(&client->dev, "kzalloc() failed\n");
 		goto err;
 	}
 
-	s->client = client;
-	mutex_init(&s->i2c_mutex);
+	mutex_init(&dev->i2c_mutex);
 
 	/* create mux i2c adapter for tuner */
-	s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
-			0, 0, 0, si2168_select, si2168_deselect);
-	if (s->adapter == NULL) {
+	dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
+			client, 0, 0, 0, si2168_select, si2168_deselect);
+	if (dev->adapter == NULL) {
 		ret = -ENODEV;
-		goto err;
+		goto err_kfree;
 	}
 
 	/* create dvb_frontend */
-	memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
-	s->fe.demodulator_priv = s;
-
-	*config->i2c_adapter = s->adapter;
-	*config->fe = &s->fe;
-	s->ts_mode = config->ts_mode;
-	s->ts_clock_inv = config->ts_clock_inv;
-	s->fw_loaded = false;
+	memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
+	dev->fe.demodulator_priv = client;
+	*config->i2c_adapter = dev->adapter;
+	*config->fe = &dev->fe;
+	dev->ts_mode = config->ts_mode;
+	dev->ts_clock_inv = config->ts_clock_inv;
+	dev->fw_loaded = false;
 
-	i2c_set_clientdata(client, s);
+	i2c_set_clientdata(client, dev);
 
-	dev_info(&s->client->dev,
-			"Silicon Labs Si2168 successfully attached\n");
+	dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n");
 	return 0;
+err_kfree:
+	kfree(dev);
 err:
-	kfree(s);
 	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2168_remove(struct i2c_client *client)
 {
-	struct si2168 *s = i2c_get_clientdata(client);
+	struct si2168_dev *dev = i2c_get_clientdata(client);
 
 	dev_dbg(&client->dev, "\n");
 
-	i2c_del_mux_adapter(s->adapter);
+	i2c_del_mux_adapter(dev->adapter);
 
-	s->fe.ops.release = NULL;
-	s->fe.demodulator_priv = NULL;
+	dev->fe.ops.release = NULL;
+	dev->fe.demodulator_priv = NULL;
 
-	kfree(s);
+	kfree(dev);
 
 	return 0;
 }
 
-static const struct i2c_device_id si2168_id[] = {
+static const struct i2c_device_id si2168_id_table[] = {
 	{"si2168", 0},
 	{}
 };
-MODULE_DEVICE_TABLE(i2c, si2168_id);
+MODULE_DEVICE_TABLE(i2c, si2168_id_table);
 
 static struct i2c_driver si2168_driver = {
 	.driver = {
@@ -743,7 +730,7 @@ static struct i2c_driver si2168_driver = {
 	},
 	.probe		= si2168_probe,
 	.remove		= si2168_remove,
-	.id_table	= si2168_id,
+	.id_table	= si2168_id_table,
 };
 
 module_i2c_driver(si2168_driver);
diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h
index 87bc12146667..70d702ae6f49 100644
--- a/drivers/media/dvb-frontends/si2168.h
+++ b/drivers/media/dvb-frontends/si2168.h
@@ -36,14 +36,12 @@ struct si2168_config {
 	struct i2c_adapter **i2c_adapter;
 
 	/* TS mode */
+#define SI2168_TS_PARALLEL	0x06
+#define SI2168_TS_SERIAL	0x03
 	u8 ts_mode;
 
 	/* TS clock inverted */
 	bool ts_clock_inv;
-
 };
 
-#define SI2168_TS_PARALLEL	0x06
-#define SI2168_TS_SERIAL	0x03
-
 #endif
diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h
index 60bc3349b6c3..aadd1367673f 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -28,8 +28,7 @@
 #define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
 
 /* state struct */
-struct si2168 {
-	struct i2c_client *client;
+struct si2168_dev {
 	struct i2c_adapter *adapter;
 	struct mutex i2c_mutex;
 	struct dvb_frontend fe;
diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c
index 93596e0e640b..3012f196e9bd 100644
--- a/drivers/media/dvb-frontends/stb0899_algo.c
+++ b/drivers/media/dvb-frontends/stb0899_algo.c
@@ -19,6 +19,7 @@
 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <linux/bitops.h>
 #include "stb0899_drv.h"
 #include "stb0899_priv.h"
 #include "stb0899_reg.h"
@@ -1490,9 +1491,7 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
 		/* Store signal parameters	*/
 		offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
 
-		/* sign extend 30 bit value before using it in calculations */
-		if (offsetfreq & (1 << 29))
-			offsetfreq |= -1 << 30;
+		offsetfreq = sign_extend32(offsetfreq, 29);
 
 		offsetfreq = offsetfreq / ((1 << 30) / 1000);
 		offsetfreq *= (internal->master_clk / 1000000);
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 19646fbb061d..c73899d3a53d 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -20,6 +20,7 @@
 */
 
 #include <linux/init.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -691,7 +692,7 @@ static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeo
 		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
 		if (!STB0899_GETFIELD(FIFOFULL, reg))
 			break;
-		if ((jiffies - start) > timeout) {
+		if (time_after(jiffies, start + timeout)) {
 			dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
 			return -ETIMEDOUT;
 		}
@@ -733,7 +734,7 @@ static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
 
 	while (!STB0899_GETFIELD(RXEND, reg)) {
 		reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
-		if (jiffies - start > timeout) {
+		if (time_after(jiffies, start + timeout)) {
 			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
 			return -ETIMEDOUT;
 		}
@@ -782,7 +783,7 @@ static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
 
 	while (!STB0899_GETFIELD(TXIDLE, reg)) {
 		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
-		if (jiffies - start > timeout) {
+		if (time_after(jiffies, start + timeout)) {
 			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
 			return -ETIMEDOUT;
 		}
diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
index b35d65c9cc05..dce22ce35d20 100644
--- a/drivers/media/dvb-frontends/tc90522.c
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -214,6 +214,7 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe)
 	state = fe->demodulator_priv;
 	c = &fe->dtv_property_cache;
 	c->delivery_system = SYS_ISDBS;
+	c->symbol_rate = 28860000;
 
 	layers = 0;
 	ret = reg_read(state, 0xe6, val, 5);
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 205d71364343..da58c9bb67c2 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -177,7 +177,7 @@ comment "Video decoders"
 
 config VIDEO_ADV7180
 	tristate "Analog Devices ADV7180 decoder"
-	depends on VIDEO_V4L2 && I2C
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
 	---help---
 	  Support for the Analog Devices ADV7180 video decoder.
 
@@ -196,7 +196,7 @@ config VIDEO_ADV7183
 
 config VIDEO_ADV7604
 	tristate "Analog Devices ADV7604 decoder"
-	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
 	---help---
 	  Support for the Analog Devices ADV7604 video decoder.
 
@@ -208,7 +208,8 @@ config VIDEO_ADV7604
 
 config VIDEO_ADV7842
 	tristate "Analog Devices ADV7842 decoder"
-	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+	select HDMI
 	---help---
 	  Support for the Analog Devices ADV7842 video decoder.
 
@@ -422,7 +423,7 @@ config VIDEO_ADV7393
 
 config VIDEO_ADV7511
 	tristate "Analog Devices ADV7511 encoder"
-	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
 	---help---
 	  Support for the Analog Devices ADV7511 video encoder.
 
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index bffe6eb528a3..b75878c27c2a 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -30,56 +30,60 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <linux/mutex.h>
-
-#define ADV7180_INPUT_CONTROL_REG			0x00
-#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM	0x00
-#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10
-#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM	0x20
-#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM	0x30
-#define ADV7180_INPUT_CONTROL_NTSC_J			0x40
-#define ADV7180_INPUT_CONTROL_NTSC_M			0x50
-#define ADV7180_INPUT_CONTROL_PAL60			0x60
-#define ADV7180_INPUT_CONTROL_NTSC_443			0x70
-#define ADV7180_INPUT_CONTROL_PAL_BG			0x80
-#define ADV7180_INPUT_CONTROL_PAL_N			0x90
-#define ADV7180_INPUT_CONTROL_PAL_M			0xa0
-#define ADV7180_INPUT_CONTROL_PAL_M_PED			0xb0
-#define ADV7180_INPUT_CONTROL_PAL_COMB_N		0xc0
-#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED		0xd0
-#define ADV7180_INPUT_CONTROL_PAL_SECAM			0xe0
-#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED		0xf0
+#include <linux/delay.h>
+
+#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM		0x0
+#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM_PED		0x1
+#define ADV7180_STD_AD_PAL_N_NTSC_J_SECAM		0x2
+#define ADV7180_STD_AD_PAL_N_NTSC_M_SECAM		0x3
+#define ADV7180_STD_NTSC_J				0x4
+#define ADV7180_STD_NTSC_M				0x5
+#define ADV7180_STD_PAL60				0x6
+#define ADV7180_STD_NTSC_443				0x7
+#define ADV7180_STD_PAL_BG				0x8
+#define ADV7180_STD_PAL_N				0x9
+#define ADV7180_STD_PAL_M				0xa
+#define ADV7180_STD_PAL_M_PED				0xb
+#define ADV7180_STD_PAL_COMB_N				0xc
+#define ADV7180_STD_PAL_COMB_N_PED			0xd
+#define ADV7180_STD_PAL_SECAM				0xe
+#define ADV7180_STD_PAL_SECAM_PED			0xf
+
+#define ADV7180_REG_INPUT_CONTROL			0x0000
 #define ADV7180_INPUT_CONTROL_INSEL_MASK		0x0f
 
-#define ADV7180_EXTENDED_OUTPUT_CONTROL_REG		0x04
+#define ADV7182_REG_INPUT_VIDSEL			0x0002
+
+#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL		0x0004
 #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS		0xC5
 
-#define ADV7180_AUTODETECT_ENABLE_REG			0x07
+#define ADV7180_REG_AUTODETECT_ENABLE			0x07
 #define ADV7180_AUTODETECT_DEFAULT			0x7f
 /* Contrast */
-#define ADV7180_CON_REG		0x08	/*Unsigned */
+#define ADV7180_REG_CON		0x0008	/*Unsigned */
 #define ADV7180_CON_MIN		0
 #define ADV7180_CON_DEF		128
 #define ADV7180_CON_MAX		255
 /* Brightness*/
-#define ADV7180_BRI_REG		0x0a	/*Signed */
+#define ADV7180_REG_BRI		0x000a	/*Signed */
 #define ADV7180_BRI_MIN		-128
 #define ADV7180_BRI_DEF		0
 #define ADV7180_BRI_MAX		127
 /* Hue */
-#define ADV7180_HUE_REG		0x0b	/*Signed, inverted */
+#define ADV7180_REG_HUE		0x000b	/*Signed, inverted */
 #define ADV7180_HUE_MIN		-127
 #define ADV7180_HUE_DEF		0
 #define ADV7180_HUE_MAX		128
 
-#define ADV7180_ADI_CTRL_REG				0x0e
-#define ADV7180_ADI_CTRL_IRQ_SPACE			0x20
+#define ADV7180_REG_CTRL		0x000e
+#define ADV7180_CTRL_IRQ_SPACE		0x20
 
-#define ADV7180_PWR_MAN_REG		0x0f
+#define ADV7180_REG_PWR_MAN		0x0f
 #define ADV7180_PWR_MAN_ON		0x04
 #define ADV7180_PWR_MAN_OFF		0x24
 #define ADV7180_PWR_MAN_RES		0x80
 
-#define ADV7180_STATUS1_REG				0x10
+#define ADV7180_REG_STATUS1		0x0010
 #define ADV7180_STATUS1_IN_LOCK		0x01
 #define ADV7180_STATUS1_AUTOD_MASK	0x70
 #define ADV7180_STATUS1_AUTOD_NTSM_M_J	0x00
@@ -91,49 +95,161 @@
 #define ADV7180_STATUS1_AUTOD_PAL_COMB	0x60
 #define ADV7180_STATUS1_AUTOD_SECAM_525	0x70
 
-#define ADV7180_IDENT_REG 0x11
+#define ADV7180_REG_IDENT 0x0011
 #define ADV7180_ID_7180 0x18
 
-#define ADV7180_ICONF1_ADI		0x40
+#define ADV7180_REG_ICONF1		0x0040
 #define ADV7180_ICONF1_ACTIVE_LOW	0x01
 #define ADV7180_ICONF1_PSYNC_ONLY	0x10
 #define ADV7180_ICONF1_ACTIVE_TO_CLR	0xC0
 /* Saturation */
-#define ADV7180_SD_SAT_CB_REG	0xe3	/*Unsigned */
-#define ADV7180_SD_SAT_CR_REG	0xe4	/*Unsigned */
+#define ADV7180_REG_SD_SAT_CB	0x00e3	/*Unsigned */
+#define ADV7180_REG_SD_SAT_CR	0x00e4	/*Unsigned */
 #define ADV7180_SAT_MIN		0
 #define ADV7180_SAT_DEF		128
 #define ADV7180_SAT_MAX		255
 
 #define ADV7180_IRQ1_LOCK	0x01
 #define ADV7180_IRQ1_UNLOCK	0x02
-#define ADV7180_ISR1_ADI	0x42
-#define ADV7180_ICR1_ADI	0x43
-#define ADV7180_IMR1_ADI	0x44
-#define ADV7180_IMR2_ADI	0x48
+#define ADV7180_REG_ISR1	0x0042
+#define ADV7180_REG_ICR1	0x0043
+#define ADV7180_REG_IMR1	0x0044
+#define ADV7180_REG_IMR2	0x0048
 #define ADV7180_IRQ3_AD_CHANGE	0x08
-#define ADV7180_ISR3_ADI	0x4A
-#define ADV7180_ICR3_ADI	0x4B
-#define ADV7180_IMR3_ADI	0x4C
-#define ADV7180_IMR4_ADI	0x50
+#define ADV7180_REG_ISR3	0x004A
+#define ADV7180_REG_ICR3	0x004B
+#define ADV7180_REG_IMR3	0x004C
+#define ADV7180_REG_IMR4	0x50
 
-#define ADV7180_NTSC_V_BIT_END_REG	0xE6
+#define ADV7180_REG_NTSC_V_BIT_END	0x00E6
 #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND	0x4F
 
+#define ADV7180_REG_VPP_SLAVE_ADDR	0xFD
+#define ADV7180_REG_CSI_SLAVE_ADDR	0xFE
+
+#define ADV7180_REG_FLCONTROL 0x40e0
+#define ADV7180_FLCONTROL_FL_ENABLE 0x1
+
+#define ADV7180_CSI_REG_PWRDN	0x00
+#define ADV7180_CSI_PWRDN	0x80
+
+#define ADV7180_INPUT_CVBS_AIN1 0x00
+#define ADV7180_INPUT_CVBS_AIN2 0x01
+#define ADV7180_INPUT_CVBS_AIN3 0x02
+#define ADV7180_INPUT_CVBS_AIN4 0x03
+#define ADV7180_INPUT_CVBS_AIN5 0x04
+#define ADV7180_INPUT_CVBS_AIN6 0x05
+#define ADV7180_INPUT_SVIDEO_AIN1_AIN2 0x06
+#define ADV7180_INPUT_SVIDEO_AIN3_AIN4 0x07
+#define ADV7180_INPUT_SVIDEO_AIN5_AIN6 0x08
+#define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09
+#define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a
+
+#define ADV7182_INPUT_CVBS_AIN1 0x00
+#define ADV7182_INPUT_CVBS_AIN2 0x01
+#define ADV7182_INPUT_CVBS_AIN3 0x02
+#define ADV7182_INPUT_CVBS_AIN4 0x03
+#define ADV7182_INPUT_CVBS_AIN5 0x04
+#define ADV7182_INPUT_CVBS_AIN6 0x05
+#define ADV7182_INPUT_CVBS_AIN7 0x06
+#define ADV7182_INPUT_CVBS_AIN8 0x07
+#define ADV7182_INPUT_SVIDEO_AIN1_AIN2 0x08
+#define ADV7182_INPUT_SVIDEO_AIN3_AIN4 0x09
+#define ADV7182_INPUT_SVIDEO_AIN5_AIN6 0x0a
+#define ADV7182_INPUT_SVIDEO_AIN7_AIN8 0x0b
+#define ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3 0x0c
+#define ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0d
+#define ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2 0x0e
+#define ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4 0x0f
+#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10
+#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11
+
+#define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44
+#define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42
+
+#define V4L2_CID_ADV_FAST_SWITCH	(V4L2_CID_USER_ADV7180_BASE + 0x00)
+
+struct adv7180_state;
+
+#define ADV7180_FLAG_RESET_POWERED	BIT(0)
+#define ADV7180_FLAG_V2			BIT(1)
+#define ADV7180_FLAG_MIPI_CSI2		BIT(2)
+#define ADV7180_FLAG_I2P		BIT(3)
+
+struct adv7180_chip_info {
+	unsigned int flags;
+	unsigned int valid_input_mask;
+	int (*set_std)(struct adv7180_state *st, unsigned int std);
+	int (*select_input)(struct adv7180_state *st, unsigned int input);
+	int (*init)(struct adv7180_state *state);
+};
+
 struct adv7180_state {
 	struct v4l2_ctrl_handler ctrl_hdl;
 	struct v4l2_subdev	sd;
+	struct media_pad	pad;
 	struct mutex		mutex; /* mutual excl. when accessing chip */
 	int			irq;
 	v4l2_std_id		curr_norm;
 	bool			autodetect;
 	bool			powered;
 	u8			input;
+
+	struct i2c_client	*client;
+	unsigned int		register_page;
+	struct i2c_client	*csi_client;
+	struct i2c_client	*vpp_client;
+	const struct adv7180_chip_info *chip_info;
+	enum v4l2_field		field;
 };
 #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler,		\
 					    struct adv7180_state,	\
 					    ctrl_hdl)->sd)
 
+static int adv7180_select_page(struct adv7180_state *state, unsigned int page)
+{
+	if (state->register_page != page) {
+		i2c_smbus_write_byte_data(state->client, ADV7180_REG_CTRL,
+			page);
+		state->register_page = page;
+	}
+
+	return 0;
+}
+
+static int adv7180_write(struct adv7180_state *state, unsigned int reg,
+	unsigned int value)
+{
+	lockdep_assert_held(&state->mutex);
+	adv7180_select_page(state, reg >> 8);
+	return i2c_smbus_write_byte_data(state->client, reg & 0xff, value);
+}
+
+static int adv7180_read(struct adv7180_state *state, unsigned int reg)
+{
+	lockdep_assert_held(&state->mutex);
+	adv7180_select_page(state, reg >> 8);
+	return i2c_smbus_read_byte_data(state->client, reg & 0xff);
+}
+
+static int adv7180_csi_write(struct adv7180_state *state, unsigned int reg,
+	unsigned int value)
+{
+	return i2c_smbus_write_byte_data(state->csi_client, reg, value);
+}
+
+static int adv7180_set_video_standard(struct adv7180_state *state,
+	unsigned int std)
+{
+	return state->chip_info->set_std(state, std);
+}
+
+static int adv7180_vpp_write(struct adv7180_state *state, unsigned int reg,
+	unsigned int value)
+{
+	return i2c_smbus_write_byte_data(state->vpp_client, reg, value);
+}
+
 static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
 {
 	/* in case V4L2_IN_ST_NO_SIGNAL */
@@ -165,22 +281,22 @@ static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
 static int v4l2_std_to_adv7180(v4l2_std_id std)
 {
 	if (std == V4L2_STD_PAL_60)
-		return ADV7180_INPUT_CONTROL_PAL60;
+		return ADV7180_STD_PAL60;
 	if (std == V4L2_STD_NTSC_443)
-		return ADV7180_INPUT_CONTROL_NTSC_443;
+		return ADV7180_STD_NTSC_443;
 	if (std == V4L2_STD_PAL_N)
-		return ADV7180_INPUT_CONTROL_PAL_N;
+		return ADV7180_STD_PAL_N;
 	if (std == V4L2_STD_PAL_M)
-		return ADV7180_INPUT_CONTROL_PAL_M;
+		return ADV7180_STD_PAL_M;
 	if (std == V4L2_STD_PAL_Nc)
-		return ADV7180_INPUT_CONTROL_PAL_COMB_N;
+		return ADV7180_STD_PAL_COMB_N;
 
 	if (std & V4L2_STD_PAL)
-		return ADV7180_INPUT_CONTROL_PAL_BG;
+		return ADV7180_STD_PAL_BG;
 	if (std & V4L2_STD_NTSC)
-		return ADV7180_INPUT_CONTROL_NTSC_M;
+		return ADV7180_STD_NTSC_M;
 	if (std & V4L2_STD_SECAM)
-		return ADV7180_INPUT_CONTROL_PAL_SECAM;
+		return ADV7180_STD_PAL_SECAM;
 
 	return -EINVAL;
 }
@@ -193,10 +309,10 @@ static u32 adv7180_status_to_v4l2(u8 status1)
 	return 0;
 }
 
-static int __adv7180_status(struct i2c_client *client, u32 *status,
+static int __adv7180_status(struct adv7180_state *state, u32 *status,
 			    v4l2_std_id *std)
 {
-	int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG);
+	int status1 = adv7180_read(state, ADV7180_REG_STATUS1);
 
 	if (status1 < 0)
 		return status1;
@@ -225,7 +341,7 @@ static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 	if (!state->autodetect || state->irq > 0)
 		*std = state->curr_norm;
 	else
-		err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);
+		err = __adv7180_status(state, NULL, std);
 
 	mutex_unlock(&state->mutex);
 	return err;
@@ -236,26 +352,19 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input,
 {
 	struct adv7180_state *state = to_state(sd);
 	int ret = mutex_lock_interruptible(&state->mutex);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
 	if (ret)
 		return ret;
 
-	/* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
-	 * all inputs and let the card driver take care of validation
-	 */
-	if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input)
+	if (input > 31 || !(BIT(input) & state->chip_info->valid_input_mask)) {
+		ret = -EINVAL;
 		goto out;
+	}
 
-	ret = i2c_smbus_read_byte_data(client, ADV7180_INPUT_CONTROL_REG);
-
-	if (ret < 0)
-		goto out;
+	ret = state->chip_info->select_input(state, input);
 
-	ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK;
-	ret = i2c_smbus_write_byte_data(client,
-					ADV7180_INPUT_CONTROL_REG, ret | input);
-	state->input = input;
+	if (ret == 0)
+		state->input = input;
 out:
 	mutex_unlock(&state->mutex);
 	return ret;
@@ -268,74 +377,104 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
 	if (ret)
 		return ret;
 
-	ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL);
+	ret = __adv7180_status(state, status, NULL);
 	mutex_unlock(&state->mutex);
 	return ret;
 }
 
+static int adv7180_program_std(struct adv7180_state *state)
+{
+	int ret;
+
+	if (state->autodetect) {
+		ret = adv7180_set_video_standard(state,
+			ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM);
+		if (ret < 0)
+			return ret;
+
+		__adv7180_status(state, NULL, &state->curr_norm);
+	} else {
+		ret = v4l2_std_to_adv7180(state->curr_norm);
+		if (ret < 0)
+			return ret;
+
+		ret = adv7180_set_video_standard(state, ret);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 {
 	struct adv7180_state *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret = mutex_lock_interruptible(&state->mutex);
+
 	if (ret)
 		return ret;
 
 	/* all standards -> autodetect */
 	if (std == V4L2_STD_ALL) {
-		ret =
-		    i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
-				ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM
-					      | state->input);
-		if (ret < 0)
-			goto out;
-
-		__adv7180_status(client, NULL, &state->curr_norm);
 		state->autodetect = true;
 	} else {
+		/* Make sure we can support this std */
 		ret = v4l2_std_to_adv7180(std);
 		if (ret < 0)
 			goto out;
 
-		ret = i2c_smbus_write_byte_data(client,
-						ADV7180_INPUT_CONTROL_REG,
-						ret | state->input);
-		if (ret < 0)
-			goto out;
-
 		state->curr_norm = std;
 		state->autodetect = false;
 	}
-	ret = 0;
+
+	ret = adv7180_program_std(state);
 out:
 	mutex_unlock(&state->mutex);
 	return ret;
 }
 
-static int adv7180_set_power(struct adv7180_state *state,
-	struct i2c_client *client, bool on)
+static int adv7180_set_power(struct adv7180_state *state, bool on)
 {
 	u8 val;
+	int ret;
 
 	if (on)
 		val = ADV7180_PWR_MAN_ON;
 	else
 		val = ADV7180_PWR_MAN_OFF;
 
-	return i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, val);
+	ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val);
+	if (ret)
+		return ret;
+
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
+		if (on) {
+			adv7180_csi_write(state, 0xDE, 0x02);
+			adv7180_csi_write(state, 0xD2, 0xF7);
+			adv7180_csi_write(state, 0xD8, 0x65);
+			adv7180_csi_write(state, 0xE0, 0x09);
+			adv7180_csi_write(state, 0x2C, 0x00);
+			if (state->field == V4L2_FIELD_NONE)
+				adv7180_csi_write(state, 0x1D, 0x80);
+			adv7180_csi_write(state, 0x00, 0x00);
+		} else {
+			adv7180_csi_write(state, 0x00, 0x80);
+		}
+	}
+
+	return 0;
 }
 
 static int adv7180_s_power(struct v4l2_subdev *sd, int on)
 {
 	struct adv7180_state *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret;
 
 	ret = mutex_lock_interruptible(&state->mutex);
 	if (ret)
 		return ret;
 
-	ret = adv7180_set_power(state, client, on);
+	ret = adv7180_set_power(state, on);
 	if (ret == 0)
 		state->powered = on;
 
@@ -347,7 +486,6 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
 	struct adv7180_state *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret = mutex_lock_interruptible(&state->mutex);
 	int val;
 
@@ -356,26 +494,36 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
 	val = ctrl->val;
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, val);
+		ret = adv7180_write(state, ADV7180_REG_BRI, val);
 		break;
 	case V4L2_CID_HUE:
 		/*Hue is inverted according to HSL chart */
-		ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, -val);
+		ret = adv7180_write(state, ADV7180_REG_HUE, -val);
 		break;
 	case V4L2_CID_CONTRAST:
-		ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, val);
+		ret = adv7180_write(state, ADV7180_REG_CON, val);
 		break;
 	case V4L2_CID_SATURATION:
 		/*
 		 *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE
 		 *Let's not confuse the user, everybody understands saturation
 		 */
-		ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG,
-						val);
+		ret = adv7180_write(state, ADV7180_REG_SD_SAT_CB, val);
 		if (ret < 0)
 			break;
-		ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG,
-						val);
+		ret = adv7180_write(state, ADV7180_REG_SD_SAT_CR, val);
+		break;
+	case V4L2_CID_ADV_FAST_SWITCH:
+		if (ctrl->val) {
+			/* ADI required write */
+			adv7180_write(state, 0x80d9, 0x44);
+			adv7180_write(state, ADV7180_REG_FLCONTROL,
+				ADV7180_FLCONTROL_FL_ENABLE);
+		} else {
+			/* ADI required write */
+			adv7180_write(state, 0x80d9, 0xc4);
+			adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00);
+		}
 		break;
 	default:
 		ret = -EINVAL;
@@ -389,6 +537,16 @@ static const struct v4l2_ctrl_ops adv7180_ctrl_ops = {
 	.s_ctrl = adv7180_s_ctrl,
 };
 
+static const struct v4l2_ctrl_config adv7180_ctrl_fast_switch = {
+	.ops = &adv7180_ctrl_ops,
+	.id = V4L2_CID_ADV_FAST_SWITCH,
+	.name = "Fast Switching",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+};
+
 static int adv7180_init_controls(struct adv7180_state *state)
 {
 	v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
@@ -405,6 +563,8 @@ static int adv7180_init_controls(struct adv7180_state *state)
 	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
 			  V4L2_CID_HUE, ADV7180_HUE_MIN,
 			  ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
+	v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);
+
 	state->sd.ctrl_handler = &state->ctrl_hdl;
 	if (state->ctrl_hdl.error) {
 		int err = state->ctrl_hdl.error;
@@ -421,13 +581,14 @@ static void adv7180_exit_controls(struct adv7180_state *state)
 	v4l2_ctrl_handler_free(&state->ctrl_hdl);
 }
 
-static int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-				 u32 *code)
+static int adv7180_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
 {
-	if (index > 0)
+	if (code->index != 0)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_YUYV8_2X8;
+	code->code = MEDIA_BUS_FMT_YUYV8_2X8;
 
 	return 0;
 }
@@ -439,23 +600,118 @@ static int adv7180_mbus_fmt(struct v4l2_subdev *sd,
 
 	fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	fmt->field = V4L2_FIELD_INTERLACED;
 	fmt->width = 720;
 	fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576;
 
 	return 0;
 }
 
+static int adv7180_set_field_mode(struct adv7180_state *state)
+{
+	if (!(state->chip_info->flags & ADV7180_FLAG_I2P))
+		return 0;
+
+	if (state->field == V4L2_FIELD_NONE) {
+		if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
+			adv7180_csi_write(state, 0x01, 0x20);
+			adv7180_csi_write(state, 0x02, 0x28);
+			adv7180_csi_write(state, 0x03, 0x38);
+			adv7180_csi_write(state, 0x04, 0x30);
+			adv7180_csi_write(state, 0x05, 0x30);
+			adv7180_csi_write(state, 0x06, 0x80);
+			adv7180_csi_write(state, 0x07, 0x70);
+			adv7180_csi_write(state, 0x08, 0x50);
+		}
+		adv7180_vpp_write(state, 0xa3, 0x00);
+		adv7180_vpp_write(state, 0x5b, 0x00);
+		adv7180_vpp_write(state, 0x55, 0x80);
+	} else {
+		if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
+			adv7180_csi_write(state, 0x01, 0x18);
+			adv7180_csi_write(state, 0x02, 0x18);
+			adv7180_csi_write(state, 0x03, 0x30);
+			adv7180_csi_write(state, 0x04, 0x20);
+			adv7180_csi_write(state, 0x05, 0x28);
+			adv7180_csi_write(state, 0x06, 0x40);
+			adv7180_csi_write(state, 0x07, 0x58);
+			adv7180_csi_write(state, 0x08, 0x30);
+		}
+		adv7180_vpp_write(state, 0xa3, 0x70);
+		adv7180_vpp_write(state, 0x5b, 0x80);
+		adv7180_vpp_write(state, 0x55, 0x00);
+	}
+
+	return 0;
+}
+
+static int adv7180_get_pad_format(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *format)
+{
+	struct adv7180_state *state = to_state(sd);
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		format->format = *v4l2_subdev_get_try_format(fh, 0);
+	} else {
+		adv7180_mbus_fmt(sd, &format->format);
+		format->format.field = state->field;
+	}
+
+	return 0;
+}
+
+static int adv7180_set_pad_format(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *format)
+{
+	struct adv7180_state *state = to_state(sd);
+	struct v4l2_mbus_framefmt *framefmt;
+
+	switch (format->format.field) {
+	case V4L2_FIELD_NONE:
+		if (!(state->chip_info->flags & ADV7180_FLAG_I2P))
+			format->format.field = V4L2_FIELD_INTERLACED;
+		break;
+	default:
+		format->format.field = V4L2_FIELD_INTERLACED;
+		break;
+	}
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		framefmt = &format->format;
+		if (state->field != format->format.field) {
+			state->field = format->format.field;
+			adv7180_set_power(state, false);
+			adv7180_set_field_mode(state);
+			adv7180_set_power(state, true);
+		}
+	} else {
+		framefmt = v4l2_subdev_get_try_format(fh, 0);
+		*framefmt = format->format;
+	}
+
+	return adv7180_mbus_fmt(sd, framefmt);
+}
+
 static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
 				 struct v4l2_mbus_config *cfg)
 {
-	/*
-	 * The ADV7180 sensor supports BT.601/656 output modes.
-	 * The BT.656 is default and not yet configurable by s/w.
-	 */
-	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
-		     V4L2_MBUS_DATA_ACTIVE_HIGH;
-	cfg->type = V4L2_MBUS_BT656;
+	struct adv7180_state *state = to_state(sd);
+
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
+		cfg->type = V4L2_MBUS_CSI2;
+		cfg->flags = V4L2_MBUS_CSI2_1_LANE |
+				V4L2_MBUS_CSI2_CHANNEL_0 |
+				V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+	} else {
+		/*
+		 * The ADV7180 sensor supports BT.601/656 output modes.
+		 * The BT.656 is default and not yet configurable by s/w.
+		 */
+		cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+				 V4L2_MBUS_DATA_ACTIVE_HIGH;
+		cfg->type = V4L2_MBUS_BT656;
+	}
 
 	return 0;
 }
@@ -465,139 +721,439 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = {
 	.querystd = adv7180_querystd,
 	.g_input_status = adv7180_g_input_status,
 	.s_routing = adv7180_s_routing,
-	.enum_mbus_fmt = adv7180_enum_mbus_fmt,
-	.try_mbus_fmt = adv7180_mbus_fmt,
-	.g_mbus_fmt = adv7180_mbus_fmt,
-	.s_mbus_fmt = adv7180_mbus_fmt,
 	.g_mbus_config = adv7180_g_mbus_config,
 };
 
+
 static const struct v4l2_subdev_core_ops adv7180_core_ops = {
 	.s_power = adv7180_s_power,
 };
 
+static const struct v4l2_subdev_pad_ops adv7180_pad_ops = {
+	.enum_mbus_code = adv7180_enum_mbus_code,
+	.set_fmt = adv7180_set_pad_format,
+	.get_fmt = adv7180_get_pad_format,
+};
+
 static const struct v4l2_subdev_ops adv7180_ops = {
 	.core = &adv7180_core_ops,
 	.video = &adv7180_video_ops,
+	.pad = &adv7180_pad_ops,
 };
 
 static irqreturn_t adv7180_irq(int irq, void *devid)
 {
 	struct adv7180_state *state = devid;
-	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
 	u8 isr3;
 
 	mutex_lock(&state->mutex);
-	i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
-				  ADV7180_ADI_CTRL_IRQ_SPACE);
-	isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI);
+	isr3 = adv7180_read(state, ADV7180_REG_ISR3);
 	/* clear */
-	i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3);
-	i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0);
+	adv7180_write(state, ADV7180_REG_ICR3, isr3);
 
 	if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect)
-		__adv7180_status(client, NULL, &state->curr_norm);
+		__adv7180_status(state, NULL, &state->curr_norm);
 	mutex_unlock(&state->mutex);
 
 	return IRQ_HANDLED;
 }
 
-static int init_device(struct i2c_client *client, struct adv7180_state *state)
+static int adv7180_init(struct adv7180_state *state)
 {
 	int ret;
 
-	/* Initialize adv7180 */
-	/* Enable autodetection */
-	if (state->autodetect) {
-		ret =
-		    i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
-				ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM
-					      | state->input);
-		if (ret < 0)
-			return ret;
-
-		ret =
-		    i2c_smbus_write_byte_data(client,
-					      ADV7180_AUTODETECT_ENABLE_REG,
-					      ADV7180_AUTODETECT_DEFAULT);
-		if (ret < 0)
-			return ret;
-	} else {
-		ret = v4l2_std_to_adv7180(state->curr_norm);
-		if (ret < 0)
-			return ret;
-
-		ret =
-		    i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
-					      ret | state->input);
-		if (ret < 0)
-			return ret;
-
-	}
 	/* ITU-R BT.656-4 compatible */
-	ret = i2c_smbus_write_byte_data(client,
-			ADV7180_EXTENDED_OUTPUT_CONTROL_REG,
+	ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
 			ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
 	if (ret < 0)
 		return ret;
 
 	/* Manually set V bit end position in NTSC mode */
-	ret = i2c_smbus_write_byte_data(client,
-					ADV7180_NTSC_V_BIT_END_REG,
+	return adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END,
 					ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
+}
+
+static int adv7180_set_std(struct adv7180_state *state, unsigned int std)
+{
+	return adv7180_write(state, ADV7180_REG_INPUT_CONTROL,
+		(std << 4) | state->input);
+}
+
+static int adv7180_select_input(struct adv7180_state *state, unsigned int input)
+{
+	int ret;
+
+	ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL);
 	if (ret < 0)
 		return ret;
 
-	/* read current norm */
-	__adv7180_status(client, NULL, &state->curr_norm);
+	ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK;
+	ret |= input;
+	return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret);
+}
 
-	/* register for interrupts */
-	if (state->irq > 0) {
-		ret = request_threaded_irq(state->irq, NULL, adv7180_irq,
-					   IRQF_ONESHOT, KBUILD_MODNAME, state);
-		if (ret)
-			return ret;
+static int adv7182_init(struct adv7180_state *state)
+{
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
+		adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR,
+			ADV7180_DEFAULT_CSI_I2C_ADDR << 1);
+
+	if (state->chip_info->flags & ADV7180_FLAG_I2P)
+		adv7180_write(state, ADV7180_REG_VPP_SLAVE_ADDR,
+			ADV7180_DEFAULT_VPP_I2C_ADDR << 1);
+
+	if (state->chip_info->flags & ADV7180_FLAG_V2) {
+		/* ADI recommended writes for improved video quality */
+		adv7180_write(state, 0x0080, 0x51);
+		adv7180_write(state, 0x0081, 0x51);
+		adv7180_write(state, 0x0082, 0x68);
+	}
 
-		ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
-						ADV7180_ADI_CTRL_IRQ_SPACE);
-		if (ret < 0)
-			goto err;
+	/* ADI required writes */
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
+		adv7180_write(state, 0x0003, 0x4e);
+		adv7180_write(state, 0x0004, 0x57);
+		adv7180_write(state, 0x001d, 0xc0);
+	} else {
+		if (state->chip_info->flags & ADV7180_FLAG_V2)
+			adv7180_write(state, 0x0004, 0x17);
+		else
+			adv7180_write(state, 0x0004, 0x07);
+		adv7180_write(state, 0x0003, 0x0c);
+		adv7180_write(state, 0x001d, 0x40);
+	}
+
+	adv7180_write(state, 0x0013, 0x00);
+
+	return 0;
+}
+
+static int adv7182_set_std(struct adv7180_state *state, unsigned int std)
+{
+	return adv7180_write(state, ADV7182_REG_INPUT_VIDSEL, std << 4);
+}
+
+enum adv7182_input_type {
+	ADV7182_INPUT_TYPE_CVBS,
+	ADV7182_INPUT_TYPE_DIFF_CVBS,
+	ADV7182_INPUT_TYPE_SVIDEO,
+	ADV7182_INPUT_TYPE_YPBPR,
+};
+
+static enum adv7182_input_type adv7182_get_input_type(unsigned int input)
+{
+	switch (input) {
+	case ADV7182_INPUT_CVBS_AIN1:
+	case ADV7182_INPUT_CVBS_AIN2:
+	case ADV7182_INPUT_CVBS_AIN3:
+	case ADV7182_INPUT_CVBS_AIN4:
+	case ADV7182_INPUT_CVBS_AIN5:
+	case ADV7182_INPUT_CVBS_AIN6:
+	case ADV7182_INPUT_CVBS_AIN7:
+	case ADV7182_INPUT_CVBS_AIN8:
+		return ADV7182_INPUT_TYPE_CVBS;
+	case ADV7182_INPUT_SVIDEO_AIN1_AIN2:
+	case ADV7182_INPUT_SVIDEO_AIN3_AIN4:
+	case ADV7182_INPUT_SVIDEO_AIN5_AIN6:
+	case ADV7182_INPUT_SVIDEO_AIN7_AIN8:
+		return ADV7182_INPUT_TYPE_SVIDEO;
+	case ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3:
+	case ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6:
+		return ADV7182_INPUT_TYPE_YPBPR;
+	case ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2:
+	case ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4:
+	case ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6:
+	case ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8:
+		return ADV7182_INPUT_TYPE_DIFF_CVBS;
+	default: /* Will never happen */
+		return 0;
+	}
+}
+
+/* ADI recommended writes to registers 0x52, 0x53, 0x54 */
+static unsigned int adv7182_lbias_settings[][3] = {
+	[ADV7182_INPUT_TYPE_CVBS] = { 0xCB, 0x4E, 0x80 },
+	[ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
+	[ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
+	[ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
+};
+
+static unsigned int adv7280_lbias_settings[][3] = {
+	[ADV7182_INPUT_TYPE_CVBS] = { 0xCD, 0x4E, 0x80 },
+	[ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
+	[ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
+	[ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
+};
+
+static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
+{
+	enum adv7182_input_type input_type;
+	unsigned int *lbias;
+	unsigned int i;
+	int ret;
+
+	ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input);
+	if (ret)
+		return ret;
+
+	/* Reset clamp circuitry - ADI recommended writes */
+	adv7180_write(state, 0x809c, 0x00);
+	adv7180_write(state, 0x809c, 0xff);
+
+	input_type = adv7182_get_input_type(input);
+
+	switch (input_type) {
+	case ADV7182_INPUT_TYPE_CVBS:
+	case ADV7182_INPUT_TYPE_DIFF_CVBS:
+		/* ADI recommends to use the SH1 filter */
+		adv7180_write(state, 0x0017, 0x41);
+		break;
+	default:
+		adv7180_write(state, 0x0017, 0x01);
+		break;
+	}
+
+	if (state->chip_info->flags & ADV7180_FLAG_V2)
+		lbias = adv7280_lbias_settings[input_type];
+	else
+		lbias = adv7182_lbias_settings[input_type];
+
+	for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++)
+		adv7180_write(state, 0x0052 + i, lbias[i]);
+
+	if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) {
+		/* ADI required writes to make differential CVBS work */
+		adv7180_write(state, 0x005f, 0xa8);
+		adv7180_write(state, 0x005a, 0x90);
+		adv7180_write(state, 0x0060, 0xb0);
+		adv7180_write(state, 0x80b6, 0x08);
+		adv7180_write(state, 0x80c0, 0xa0);
+	} else {
+		adv7180_write(state, 0x005f, 0xf0);
+		adv7180_write(state, 0x005a, 0xd0);
+		adv7180_write(state, 0x0060, 0x10);
+		adv7180_write(state, 0x80b6, 0x9c);
+		adv7180_write(state, 0x80c0, 0x00);
+	}
+
+	return 0;
+}
+
+static const struct adv7180_chip_info adv7180_info = {
+	.flags = ADV7180_FLAG_RESET_POWERED,
+	/* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
+	 * all inputs and let the card driver take care of validation
+	 */
+	.valid_input_mask = BIT(ADV7180_INPUT_CVBS_AIN1) |
+		BIT(ADV7180_INPUT_CVBS_AIN2) |
+		BIT(ADV7180_INPUT_CVBS_AIN3) |
+		BIT(ADV7180_INPUT_CVBS_AIN4) |
+		BIT(ADV7180_INPUT_CVBS_AIN5) |
+		BIT(ADV7180_INPUT_CVBS_AIN6) |
+		BIT(ADV7180_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7180_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7180_INPUT_SVIDEO_AIN5_AIN6) |
+		BIT(ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3) |
+		BIT(ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6),
+	.init = adv7180_init,
+	.set_std = adv7180_set_std,
+	.select_input = adv7180_select_input,
+};
+
+static const struct adv7180_chip_info adv7182_info = {
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN3) |
+		BIT(ADV7182_INPUT_CVBS_AIN4) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static const struct adv7180_chip_info adv7280_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN3) |
+		BIT(ADV7182_INPUT_CVBS_AIN4) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static const struct adv7180_chip_info adv7280_m_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN3) |
+		BIT(ADV7182_INPUT_CVBS_AIN4) |
+		BIT(ADV7182_INPUT_CVBS_AIN5) |
+		BIT(ADV7182_INPUT_CVBS_AIN6) |
+		BIT(ADV7182_INPUT_CVBS_AIN7) |
+		BIT(ADV7182_INPUT_CVBS_AIN8) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
+		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
+		BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static const struct adv7180_chip_info adv7281_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN7) |
+		BIT(ADV7182_INPUT_CVBS_AIN8) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static const struct adv7180_chip_info adv7281_m_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN3) |
+		BIT(ADV7182_INPUT_CVBS_AIN4) |
+		BIT(ADV7182_INPUT_CVBS_AIN7) |
+		BIT(ADV7182_INPUT_CVBS_AIN8) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
+		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
 
+static const struct adv7180_chip_info adv7281_ma_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN3) |
+		BIT(ADV7182_INPUT_CVBS_AIN4) |
+		BIT(ADV7182_INPUT_CVBS_AIN5) |
+		BIT(ADV7182_INPUT_CVBS_AIN6) |
+		BIT(ADV7182_INPUT_CVBS_AIN7) |
+		BIT(ADV7182_INPUT_CVBS_AIN8) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
+		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
+		BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static const struct adv7180_chip_info adv7282_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN7) |
+		BIT(ADV7182_INPUT_CVBS_AIN8) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static const struct adv7180_chip_info adv7282_m_info = {
+	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
+	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
+		BIT(ADV7182_INPUT_CVBS_AIN2) |
+		BIT(ADV7182_INPUT_CVBS_AIN3) |
+		BIT(ADV7182_INPUT_CVBS_AIN4) |
+		BIT(ADV7182_INPUT_CVBS_AIN7) |
+		BIT(ADV7182_INPUT_CVBS_AIN8) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
+		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
+	.init = adv7182_init,
+	.set_std = adv7182_set_std,
+	.select_input = adv7182_select_input,
+};
+
+static int init_device(struct adv7180_state *state)
+{
+	int ret;
+
+	mutex_lock(&state->mutex);
+
+	adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);
+	usleep_range(2000, 10000);
+
+	ret = state->chip_info->init(state);
+	if (ret)
+		goto out_unlock;
+
+	ret = adv7180_program_std(state);
+	if (ret)
+		goto out_unlock;
+
+	adv7180_set_field_mode(state);
+
+	/* register for interrupts */
+	if (state->irq > 0) {
 		/* config the Interrupt pin to be active low */
-		ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI,
+		ret = adv7180_write(state, ADV7180_REG_ICONF1,
 						ADV7180_ICONF1_ACTIVE_LOW |
 						ADV7180_ICONF1_PSYNC_ONLY);
 		if (ret < 0)
-			goto err;
+			goto out_unlock;
 
-		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0);
+		ret = adv7180_write(state, ADV7180_REG_IMR1, 0);
 		if (ret < 0)
-			goto err;
+			goto out_unlock;
 
-		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0);
+		ret = adv7180_write(state, ADV7180_REG_IMR2, 0);
 		if (ret < 0)
-			goto err;
+			goto out_unlock;
 
 		/* enable AD change interrupts interrupts */
-		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI,
+		ret = adv7180_write(state, ADV7180_REG_IMR3,
 						ADV7180_IRQ3_AD_CHANGE);
 		if (ret < 0)
-			goto err;
+			goto out_unlock;
 
-		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0);
+		ret = adv7180_write(state, ADV7180_REG_IMR4, 0);
 		if (ret < 0)
-			goto err;
-
-		ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
-						0);
-		if (ret < 0)
-			goto err;
+			goto out_unlock;
 	}
 
-	return 0;
+out_unlock:
+	mutex_unlock(&state->mutex);
 
-err:
-	free_irq(state->irq, state);
 	return ret;
 }
 
@@ -616,26 +1172,63 @@ static int adv7180_probe(struct i2c_client *client,
 		 client->addr, client->adapter->name);
 
 	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
-	if (state == NULL) {
-		ret = -ENOMEM;
-		goto err;
+	if (state == NULL)
+		return -ENOMEM;
+
+	state->client = client;
+	state->field = V4L2_FIELD_INTERLACED;
+	state->chip_info = (struct adv7180_chip_info *)id->driver_data;
+
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
+		state->csi_client = i2c_new_dummy(client->adapter,
+				ADV7180_DEFAULT_CSI_I2C_ADDR);
+		if (!state->csi_client)
+			return -ENOMEM;
+	}
+
+	if (state->chip_info->flags & ADV7180_FLAG_I2P) {
+		state->vpp_client = i2c_new_dummy(client->adapter,
+				ADV7180_DEFAULT_VPP_I2C_ADDR);
+		if (!state->vpp_client) {
+			ret = -ENOMEM;
+			goto err_unregister_csi_client;
+		}
 	}
 
 	state->irq = client->irq;
 	mutex_init(&state->mutex);
 	state->autodetect = true;
-	state->powered = true;
+	if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED)
+		state->powered = true;
+	else
+		state->powered = false;
 	state->input = 0;
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
+	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 	ret = adv7180_init_controls(state);
 	if (ret)
-		goto err_unreg_subdev;
-	ret = init_device(client, state);
+		goto err_unregister_vpp_client;
+
+	state->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
+	ret = media_entity_init(&sd->entity, 1, &state->pad, 0);
 	if (ret)
 		goto err_free_ctrl;
 
+	ret = init_device(state);
+	if (ret)
+		goto err_media_entity_cleanup;
+
+	if (state->irq) {
+		ret = request_threaded_irq(client->irq, NULL, adv7180_irq,
+					   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+					   KBUILD_MODNAME, state);
+		if (ret)
+			goto err_media_entity_cleanup;
+	}
+
 	ret = v4l2_async_register_subdev(sd);
 	if (ret)
 		goto err_free_irq;
@@ -645,11 +1238,17 @@ static int adv7180_probe(struct i2c_client *client,
 err_free_irq:
 	if (state->irq > 0)
 		free_irq(client->irq, state);
+err_media_entity_cleanup:
+	media_entity_cleanup(&sd->entity);
 err_free_ctrl:
 	adv7180_exit_controls(state);
-err_unreg_subdev:
+err_unregister_vpp_client:
+	if (state->chip_info->flags & ADV7180_FLAG_I2P)
+		i2c_unregister_device(state->vpp_client);
+err_unregister_csi_client:
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
+		i2c_unregister_device(state->csi_client);
 	mutex_destroy(&state->mutex);
-err:
 	return ret;
 }
 
@@ -663,15 +1262,32 @@ static int adv7180_remove(struct i2c_client *client)
 	if (state->irq > 0)
 		free_irq(client->irq, state);
 
+	media_entity_cleanup(&sd->entity);
 	adv7180_exit_controls(state);
+
+	if (state->chip_info->flags & ADV7180_FLAG_I2P)
+		i2c_unregister_device(state->vpp_client);
+	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
+		i2c_unregister_device(state->csi_client);
+
 	mutex_destroy(&state->mutex);
+
 	return 0;
 }
 
 static const struct i2c_device_id adv7180_id[] = {
-	{KBUILD_MODNAME, 0},
+	{ "adv7180", (kernel_ulong_t)&adv7180_info },
+	{ "adv7182", (kernel_ulong_t)&adv7182_info },
+	{ "adv7280", (kernel_ulong_t)&adv7280_info },
+	{ "adv7280-m", (kernel_ulong_t)&adv7280_m_info },
+	{ "adv7281", (kernel_ulong_t)&adv7281_info },
+	{ "adv7281-m", (kernel_ulong_t)&adv7281_m_info },
+	{ "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info },
+	{ "adv7282", (kernel_ulong_t)&adv7282_info },
+	{ "adv7282-m", (kernel_ulong_t)&adv7282_m_info },
 	{},
 };
+MODULE_DEVICE_TABLE(i2c, adv7180_id);
 
 #ifdef CONFIG_PM_SLEEP
 static int adv7180_suspend(struct device *dev)
@@ -680,7 +1296,7 @@ static int adv7180_suspend(struct device *dev)
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct adv7180_state *state = to_state(sd);
 
-	return adv7180_set_power(state, client, false);
+	return adv7180_set_power(state, false);
 }
 
 static int adv7180_resume(struct device *dev)
@@ -690,14 +1306,14 @@ static int adv7180_resume(struct device *dev)
 	struct adv7180_state *state = to_state(sd);
 	int ret;
 
-	if (state->powered) {
-		ret = adv7180_set_power(state, client, true);
-		if (ret)
-			return ret;
-	}
-	ret = init_device(client, state);
+	ret = init_device(state);
 	if (ret < 0)
 		return ret;
+
+	ret = adv7180_set_power(state, state->powered);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -708,8 +1324,6 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume);
 #define ADV7180_PM_OPS NULL
 #endif
 
-MODULE_DEVICE_TABLE(i2c, adv7180_id);
-
 static struct i2c_driver adv7180_driver = {
 	.driver = {
 		   .owner = THIS_MODULE,
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index e43dd2e2a38a..d228b7c82310 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -333,21 +333,11 @@ static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
 	return container_of(sd, struct adv7604_state, sd);
 }
 
-static inline unsigned hblanking(const struct v4l2_bt_timings *t)
-{
-	return V4L2_DV_BT_BLANKING_WIDTH(t);
-}
-
 static inline unsigned htotal(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_FRAME_WIDTH(t);
 }
 
-static inline unsigned vblanking(const struct v4l2_bt_timings *t)
-{
-	return V4L2_DV_BT_BLANKING_HEIGHT(t);
-}
-
 static inline unsigned vtotal(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_FRAME_HEIGHT(t);
@@ -466,11 +456,6 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
 }
 
-static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
-{
-	return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
-}
-
 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
@@ -486,34 +471,6 @@ static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 					 reg, val);
 }
 
-static inline int esdp_read(struct v4l2_subdev *sd, u8 reg)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	return adv_smbus_read_byte_data(state, ADV7604_PAGE_ESDP, reg);
-}
-
-static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	return adv_smbus_write_byte_data(state, ADV7604_PAGE_ESDP, reg, val);
-}
-
-static inline int dpp_read(struct v4l2_subdev *sd, u8 reg)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	return adv_smbus_read_byte_data(state, ADV7604_PAGE_DPP, reg);
-}
-
-static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	return adv_smbus_write_byte_data(state, ADV7604_PAGE_DPP, reg, val);
-}
-
 static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
@@ -561,32 +518,6 @@ static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val);
 }
 
-static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
-{
-	struct adv7604_state *state = to_state(sd);
-	struct i2c_client *client = state->i2c_clients[ADV7604_PAGE_EDID];
-	u8 msgbuf0[1] = { 0 };
-	u8 msgbuf1[256];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = client->addr,
-			.len = 1,
-			.buf = msgbuf0
-		},
-		{
-			.addr = client->addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = msgbuf1
-		},
-	};
-
-	if (i2c_transfer(client->adapter, msg, 2) < 0)
-		return -EIO;
-	memcpy(val, msgbuf1, len);
-	return 0;
-}
-
 static inline int edid_write_block(struct v4l2_subdev *sd,
 					unsigned len, const u8 *val)
 {
@@ -652,13 +583,6 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
 	return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
 }
 
-static inline int test_read(struct v4l2_subdev *sd, u8 reg)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	return adv_smbus_read_byte_data(state, ADV7604_PAGE_TEST, reg);
-}
-
 static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 75d26dfd0939..7c215ee142c4 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -38,6 +38,7 @@
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
 #include <linux/v4l2-dv-timings.h>
+#include <linux/hdmi.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-dv-timings.h>
@@ -220,21 +221,11 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
 	return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
 }
 
-static inline unsigned hblanking(const struct v4l2_bt_timings *t)
-{
-	return V4L2_DV_BT_BLANKING_WIDTH(t);
-}
-
 static inline unsigned htotal(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_FRAME_WIDTH(t);
 }
 
-static inline unsigned vblanking(const struct v4l2_bt_timings *t)
-{
-	return V4L2_DV_BT_BLANKING_HEIGHT(t);
-}
-
 static inline unsigned vtotal(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_FRAME_HEIGHT(t);
@@ -2108,149 +2099,65 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)
 	return err;
 }
 
-/*********** avi info frame CEA-861-E **************/
-/* TODO move to common library */
-
-struct avi_info_frame {
-	uint8_t f17;
-	uint8_t y10;
-	uint8_t a0;
-	uint8_t b10;
-	uint8_t s10;
-	uint8_t c10;
-	uint8_t m10;
-	uint8_t r3210;
-	uint8_t itc;
-	uint8_t ec210;
-	uint8_t q10;
-	uint8_t sc10;
-	uint8_t f47;
-	uint8_t vic;
-	uint8_t yq10;
-	uint8_t cn10;
-	uint8_t pr3210;
-	uint16_t etb;
-	uint16_t sbb;
-	uint16_t elb;
-	uint16_t srb;
-};
-
-static const char *y10_txt[4] = {
-	"RGB",
-	"YCbCr 4:2:2",
-	"YCbCr 4:4:4",
-	"Future",
-};
-
-static const char *c10_txt[4] = {
-	"No Data",
-	"SMPTE 170M",
-	"ITU-R 709",
-	"Extended Colorimetry information valied",
-};
-
-static const char *itc_txt[2] = {
-	"No Data",
-	"IT content",
-};
-
-static const char *ec210_txt[8] = {
-	"xvYCC601",
-	"xvYCC709",
-	"sYCC601",
-	"AdobeYCC601",
-	"AdobeRGB",
-	"5 reserved",
-	"6 reserved",
-	"7 reserved",
+struct adv7842_cfg_read_infoframe {
+	const char *desc;
+	u8 present_mask;
+	u8 head_addr;
+	u8 payload_addr;
 };
 
-static const char *q10_txt[4] = {
-	"Default",
-	"Limited Range",
-	"Full Range",
-	"Reserved",
-};
-
-static void parse_avi_infoframe(struct v4l2_subdev *sd, uint8_t *buf,
-				struct avi_info_frame *avi)
-{
-	avi->f17 = (buf[1] >> 7) & 0x1;
-	avi->y10 = (buf[1] >> 5) & 0x3;
-	avi->a0 = (buf[1] >> 4) & 0x1;
-	avi->b10 = (buf[1] >> 2) & 0x3;
-	avi->s10 = buf[1] & 0x3;
-	avi->c10 = (buf[2] >> 6) & 0x3;
-	avi->m10 = (buf[2] >> 4) & 0x3;
-	avi->r3210 = buf[2] & 0xf;
-	avi->itc = (buf[3] >> 7) & 0x1;
-	avi->ec210 = (buf[3] >> 4) & 0x7;
-	avi->q10 = (buf[3] >> 2) & 0x3;
-	avi->sc10 = buf[3] & 0x3;
-	avi->f47 = (buf[4] >> 7) & 0x1;
-	avi->vic = buf[4] & 0x7f;
-	avi->yq10 = (buf[5] >> 6) & 0x3;
-	avi->cn10 = (buf[5] >> 4) & 0x3;
-	avi->pr3210 = buf[5] & 0xf;
-	avi->etb = buf[6] + 256*buf[7];
-	avi->sbb = buf[8] + 256*buf[9];
-	avi->elb = buf[10] + 256*buf[11];
-	avi->srb = buf[12] + 256*buf[13];
-}
-
-static void print_avi_infoframe(struct v4l2_subdev *sd)
+static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infoframe *cri)
 {
 	int i;
-	uint8_t buf[14];
-	u8 avi_len;
-	u8 avi_ver;
-	struct avi_info_frame avi;
+	uint8_t buffer[32];
+	union hdmi_infoframe frame;
+	u8 len;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct device *dev = &client->dev;
 
-	if (!(hdmi_read(sd, 0x05) & 0x80)) {
-		v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
-		return;
-	}
-	if (!(io_read(sd, 0x60) & 0x01)) {
-		v4l2_info(sd, "AVI infoframe not received\n");
+	if (!(io_read(sd, 0x60) & cri->present_mask)) {
+		v4l2_info(sd, "%s infoframe not received\n", cri->desc);
 		return;
 	}
 
-	if (io_read(sd, 0x88) & 0x10) {
-		v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
-		io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */
-		if (io_read(sd, 0x88) & 0x10) {
-			v4l2_info(sd, "AVI infoframe checksum error still present\n");
-			io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */
-		}
-	}
+	for (i = 0; i < 3; i++)
+		buffer[i] = infoframe_read(sd, cri->head_addr + i);
 
-	avi_len = infoframe_read(sd, 0xe2);
-	avi_ver = infoframe_read(sd, 0xe1);
-	v4l2_info(sd, "AVI infoframe version %d (%d byte)\n",
-		  avi_ver, avi_len);
+	len = buffer[2] + 1;
 
-	if (avi_ver != 0x02)
+	if (len + 3 > sizeof(buffer)) {
+		v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
 		return;
+	}
+
+	for (i = 0; i < len; i++)
+		buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i);
 
-	for (i = 0; i < 14; i++)
-		buf[i] = infoframe_read(sd, i);
+	if (hdmi_infoframe_unpack(&frame, buffer) < 0) {
+		v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
+		return;
+	}
 
-	v4l2_info(sd, "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		  buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
-		  buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
+	hdmi_infoframe_log(KERN_INFO, dev, &frame);
+}
 
-	parse_avi_infoframe(sd, buf, &avi);
+static void adv7842_log_infoframes(struct v4l2_subdev *sd)
+{
+	int i;
+	struct adv7842_cfg_read_infoframe cri[] = {
+		{ "AVI", 0x01, 0xe0, 0x00 },
+		{ "Audio", 0x02, 0xe3, 0x1c },
+		{ "SDP", 0x04, 0xe6, 0x2a },
+		{ "Vendor", 0x10, 0xec, 0x54 }
+	};
 
-	if (avi.vic)
-		v4l2_info(sd, "\tVIC: %d\n", avi.vic);
-	if (avi.itc)
-		v4l2_info(sd, "\t%s\n", itc_txt[avi.itc]);
+	if (!(hdmi_read(sd, 0x05) & 0x80)) {
+		v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
+		return;
+	}
 
-	if (avi.y10)
-		v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], !avi.c10 ? "" :
-			(avi.c10 == 0x3 ? ec210_txt[avi.ec210] : c10_txt[avi.c10]));
-	else
-		v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], q10_txt[avi.q10]);
+	for (i = 0; i < ARRAY_SIZE(cri); i++)
+		log_infoframe(sd, &cri[i]);
 }
 
 static const char * const prim_mode_txt[] = {
@@ -2464,7 +2371,8 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
 	v4l2_info(sd, "Deep color mode: %s\n",
 			deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]);
 
-	print_avi_infoframe(sd);
+	adv7842_log_infoframes(sd);
+
 	return 0;
 }
 
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
index 2820f7c38cba..6ed16e569bbf 100644
--- a/drivers/media/i2c/m5mols/m5mols_core.c
+++ b/drivers/media/i2c/m5mols/m5mols_core.c
@@ -125,9 +125,9 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
 	if (length == 1)
 		return *data;
 	else if (length == 2)
-		return be16_to_cpu(*((u16 *)data));
+		return be16_to_cpu(*((__be16 *)data));
 	else
-		return be32_to_cpu(*((u32 *)data));
+		return be32_to_cpu(*((__be32 *)data));
 }
 
 /**
@@ -454,11 +454,6 @@ static int m5mols_get_version(struct v4l2_subdev *sd)
 			return ret;
 	}
 
-	ver->fw = be16_to_cpu(ver->fw);
-	ver->hw = be16_to_cpu(ver->hw);
-	ver->param = be16_to_cpu(ver->param);
-	ver->awb = be16_to_cpu(ver->awb);
-
 	v4l2_info(sd, "Manufacturer\t[%s]\n",
 			is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
 			"Samsung Electro-Machanics" :
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
index 4d9c6bc34265..dcc68ec71732 100644
--- a/drivers/media/i2c/msp3400-driver.c
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -904,11 +904,3 @@ static struct i2c_driver msp_driver = {
 };
 
 module_i2c_driver(msp_driver);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c
index 45b3fca188ca..76431223f0ff 100644
--- a/drivers/media/i2c/mt9m032.c
+++ b/drivers/media/i2c/mt9m032.c
@@ -422,22 +422,25 @@ done:
 	return ret;
 }
 
-static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev,
-				struct v4l2_subdev_fh *fh,
-				struct v4l2_subdev_crop *crop)
+static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
+				     struct v4l2_subdev_fh *fh,
+				     struct v4l2_subdev_selection *sel)
 {
 	struct mt9m032 *sensor = to_mt9m032(subdev);
 
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
 	mutex_lock(&sensor->lock);
-	crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which);
+	sel->r = *__mt9m032_get_pad_crop(sensor, fh, sel->which);
 	mutex_unlock(&sensor->lock);
 
 	return 0;
 }
 
-static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
-				struct v4l2_subdev_fh *fh,
-				struct v4l2_subdev_crop *crop)
+static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
+				     struct v4l2_subdev_fh *fh,
+				     struct v4l2_subdev_selection *sel)
 {
 	struct mt9m032 *sensor = to_mt9m032(subdev);
 	struct v4l2_mbus_framefmt *format;
@@ -445,9 +448,12 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
 	struct v4l2_rect rect;
 	int ret = 0;
 
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
 	mutex_lock(&sensor->lock);
 
-	if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+	if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 		ret = -EBUSY;
 		goto done;
 	}
@@ -455,13 +461,13 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
 	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
 	 * pixels to ensure a GRBG Bayer pattern.
 	 */
-	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN,
+	rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN,
 			  MT9M032_COLUMN_START_MAX);
-	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN,
+	rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN,
 			 MT9M032_ROW_START_MAX);
-	rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
+	rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
 			     MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX);
-	rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
+	rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
 			      MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX);
 
 	rect.width = min_t(unsigned int, rect.width,
@@ -469,21 +475,21 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
 	rect.height = min_t(unsigned int, rect.height,
 			    MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
 
-	__crop = __mt9m032_get_pad_crop(sensor, fh, crop->which);
+	__crop = __mt9m032_get_pad_crop(sensor, fh, sel->which);
 
 	if (rect.width != __crop->width || rect.height != __crop->height) {
 		/* Reset the output image size if the crop rectangle size has
 		 * been modified.
 		 */
-		format = __mt9m032_get_pad_format(sensor, fh, crop->which);
+		format = __mt9m032_get_pad_format(sensor, fh, sel->which);
 		format->width = rect.width;
 		format->height = rect.height;
 	}
 
 	*__crop = rect;
-	crop->rect = rect;
+	sel->r = rect;
 
-	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 		ret = mt9m032_update_geom_timing(sensor);
 
 done:
@@ -690,8 +696,8 @@ static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
 	.enum_frame_size = mt9m032_enum_frame_size,
 	.get_fmt = mt9m032_get_pad_format,
 	.set_fmt = mt9m032_set_pad_format,
-	.set_crop = mt9m032_set_pad_crop,
-	.get_crop = mt9m032_get_pad_crop,
+	.set_selection = mt9m032_set_pad_selection,
+	.get_selection = mt9m032_get_pad_selection,
 };
 
 static const struct v4l2_subdev_ops mt9m032_ops = {
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index edb76bd33d16..e3acae9a2ec3 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -581,37 +581,42 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev,
 	return 0;
 }
 
-static int mt9p031_get_crop(struct v4l2_subdev *subdev,
-			    struct v4l2_subdev_fh *fh,
-			    struct v4l2_subdev_crop *crop)
+static int mt9p031_get_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
 {
 	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
 
-	crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
-					     crop->which);
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	sel->r = *__mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
 	return 0;
 }
 
-static int mt9p031_set_crop(struct v4l2_subdev *subdev,
-			    struct v4l2_subdev_fh *fh,
-			    struct v4l2_subdev_crop *crop)
+static int mt9p031_set_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
 {
 	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
 	struct v4l2_mbus_framefmt *__format;
 	struct v4l2_rect *__crop;
 	struct v4l2_rect rect;
 
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
 	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
 	 * pixels to ensure a GRBG Bayer pattern.
 	 */
-	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN,
+	rect.left = clamp(ALIGN(sel->r.left, 2), MT9P031_COLUMN_START_MIN,
 			  MT9P031_COLUMN_START_MAX);
-	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN,
+	rect.top = clamp(ALIGN(sel->r.top, 2), MT9P031_ROW_START_MIN,
 			 MT9P031_ROW_START_MAX);
-	rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
+	rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
 			     MT9P031_WINDOW_WIDTH_MIN,
 			     MT9P031_WINDOW_WIDTH_MAX);
-	rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
+	rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
 			      MT9P031_WINDOW_HEIGHT_MIN,
 			      MT9P031_WINDOW_HEIGHT_MAX);
 
@@ -620,20 +625,20 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
 	rect.height = min_t(unsigned int, rect.height,
 			    MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
 
-	__crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
 
 	if (rect.width != __crop->width || rect.height != __crop->height) {
 		/* Reset the output image size if the crop rectangle size has
 		 * been modified.
 		 */
-		__format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
-						    crop->which);
+		__format = __mt9p031_get_pad_format(mt9p031, fh, sel->pad,
+						    sel->which);
 		__format->width = rect.width;
 		__format->height = rect.height;
 	}
 
 	*__crop = rect;
-	crop->rect = rect;
+	sel->r = rect;
 
 	return 0;
 }
@@ -980,8 +985,8 @@ static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
 	.enum_frame_size = mt9p031_enum_frame_size,
 	.get_fmt = mt9p031_get_format,
 	.set_fmt = mt9p031_set_format,
-	.get_crop = mt9p031_get_crop,
-	.set_crop = mt9p031_set_crop,
+	.get_selection = mt9p031_get_selection,
+	.set_selection = mt9p031_set_selection,
 };
 
 static struct v4l2_subdev_ops mt9p031_subdev_ops = {
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
index d9e9889b579f..f6ca636b538d 100644
--- a/drivers/media/i2c/mt9t001.c
+++ b/drivers/media/i2c/mt9t001.c
@@ -401,39 +401,44 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev,
 	return 0;
 }
 
-static int mt9t001_get_crop(struct v4l2_subdev *subdev,
-			    struct v4l2_subdev_fh *fh,
-			    struct v4l2_subdev_crop *crop)
+static int mt9t001_get_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
 {
 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
 
-	crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
-					     crop->which);
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	sel->r = *__mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
 	return 0;
 }
 
-static int mt9t001_set_crop(struct v4l2_subdev *subdev,
-			    struct v4l2_subdev_fh *fh,
-			    struct v4l2_subdev_crop *crop)
+static int mt9t001_set_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
 {
 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
 	struct v4l2_mbus_framefmt *__format;
 	struct v4l2_rect *__crop;
 	struct v4l2_rect rect;
 
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
 	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
 	 * pixels.
 	 */
-	rect.left = clamp(ALIGN(crop->rect.left, 2),
+	rect.left = clamp(ALIGN(sel->r.left, 2),
 			  MT9T001_COLUMN_START_MIN,
 			  MT9T001_COLUMN_START_MAX);
-	rect.top = clamp(ALIGN(crop->rect.top, 2),
+	rect.top = clamp(ALIGN(sel->r.top, 2),
 			 MT9T001_ROW_START_MIN,
 			 MT9T001_ROW_START_MAX);
-	rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
+	rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
 			     MT9T001_WINDOW_WIDTH_MIN + 1,
 			     MT9T001_WINDOW_WIDTH_MAX + 1);
-	rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
+	rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
 			      MT9T001_WINDOW_HEIGHT_MIN + 1,
 			      MT9T001_WINDOW_HEIGHT_MAX + 1);
 
@@ -442,20 +447,20 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
 	rect.height = min_t(unsigned int, rect.height,
 			    MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
 
-	__crop = __mt9t001_get_pad_crop(mt9t001, fh, crop->pad, crop->which);
+	__crop = __mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
 
 	if (rect.width != __crop->width || rect.height != __crop->height) {
 		/* Reset the output image size if the crop rectangle size has
 		 * been modified.
 		 */
-		__format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad,
-						    crop->which);
+		__format = __mt9t001_get_pad_format(mt9t001, fh, sel->pad,
+						    sel->which);
 		__format->width = rect.width;
 		__format->height = rect.height;
 	}
 
 	*__crop = rect;
-	crop->rect = rect;
+	sel->r = rect;
 
 	return 0;
 }
@@ -819,8 +824,8 @@ static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
 	.enum_frame_size = mt9t001_enum_frame_size,
 	.get_fmt = mt9t001_get_format,
 	.set_fmt = mt9t001_set_format,
-	.get_crop = mt9t001_get_crop,
-	.set_crop = mt9t001_set_crop,
+	.get_selection = mt9t001_get_selection,
+	.set_selection = mt9t001_set_selection,
 };
 
 static struct v4l2_subdev_ops mt9t001_subdev_ops = {
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 93687c1e4097..bd3f979a4d49 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -552,39 +552,44 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
 	return 0;
 }
 
-static int mt9v032_get_crop(struct v4l2_subdev *subdev,
-			    struct v4l2_subdev_fh *fh,
-			    struct v4l2_subdev_crop *crop)
+static int mt9v032_get_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
 {
 	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
 
-	crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
-					     crop->which);
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	sel->r = *__mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
 	return 0;
 }
 
-static int mt9v032_set_crop(struct v4l2_subdev *subdev,
-			    struct v4l2_subdev_fh *fh,
-			    struct v4l2_subdev_crop *crop)
+static int mt9v032_set_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
 {
 	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
 	struct v4l2_mbus_framefmt *__format;
 	struct v4l2_rect *__crop;
 	struct v4l2_rect rect;
 
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
 	/* Clamp the crop rectangle boundaries and align them to a non multiple
 	 * of 2 pixels to ensure a GRBG Bayer pattern.
 	 */
-	rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
+	rect.left = clamp(ALIGN(sel->r.left + 1, 2) - 1,
 			  MT9V032_COLUMN_START_MIN,
 			  MT9V032_COLUMN_START_MAX);
-	rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
+	rect.top = clamp(ALIGN(sel->r.top + 1, 2) - 1,
 			 MT9V032_ROW_START_MIN,
 			 MT9V032_ROW_START_MAX);
-	rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
+	rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
 			     MT9V032_WINDOW_WIDTH_MIN,
 			     MT9V032_WINDOW_WIDTH_MAX);
-	rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
+	rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
 			      MT9V032_WINDOW_HEIGHT_MIN,
 			      MT9V032_WINDOW_HEIGHT_MAX);
 
@@ -593,17 +598,17 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
 	rect.height = min_t(unsigned int,
 			    rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
 
-	__crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
+	__crop = __mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
 
 	if (rect.width != __crop->width || rect.height != __crop->height) {
 		/* Reset the output image size if the crop rectangle size has
 		 * been modified.
 		 */
-		__format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
-						    crop->which);
+		__format = __mt9v032_get_pad_format(mt9v032, fh, sel->pad,
+						    sel->which);
 		__format->width = rect.width;
 		__format->height = rect.height;
-		if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 			mt9v032->hratio = 1;
 			mt9v032->vratio = 1;
 			mt9v032_configure_pixel_rate(mt9v032);
@@ -611,7 +616,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
 	}
 
 	*__crop = rect;
-	crop->rect = rect;
+	sel->r = rect;
 
 	return 0;
 }
@@ -844,8 +849,8 @@ static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
 	.enum_frame_size = mt9v032_enum_frame_size,
 	.get_fmt = mt9v032_get_format,
 	.set_fmt = mt9v032_set_format,
-	.get_crop = mt9v032_get_crop,
-	.set_crop = mt9v032_set_crop,
+	.get_selection = mt9v032_get_selection,
+	.set_selection = mt9v032_set_selection,
 };
 
 static struct v4l2_subdev_ops mt9v032_subdev_ops = {
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index d1c50c9d43ae..70071314789e 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -220,7 +220,7 @@ static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
 	msg[1].buf = rbuf;
 
 	ret = i2c_transfer(client->adapter, msg, 2);
-	*val = be16_to_cpu(*((u16 *)rbuf));
+	*val = be16_to_cpu(*((__be16 *)rbuf));
 
 	v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
 
@@ -341,7 +341,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
 		v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE);
 		return err;
 	}
-	regs_num = le32_to_cpu(get_unaligned_le32(fw->data));
+	regs_num = get_unaligned_le32(fw->data);
 
 	v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
 		 S5K4ECGX_FIRMWARE, fw->size, regs_num);
@@ -351,8 +351,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
 		err = -EINVAL;
 		goto fw_out;
 	}
-	crc_file = le32_to_cpu(get_unaligned_le32(fw->data +
-						  regs_num * FW_RECORD_SIZE));
+	crc_file = get_unaligned_le32(fw->data + regs_num * FW_RECORD_SIZE);
 	crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE);
 	if (crc != crc_file) {
 		v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file);
@@ -361,9 +360,9 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
 	}
 	ptr = fw->data + FW_RECORD_SIZE;
 	for (i = 1; i < regs_num; i++) {
-		addr = le32_to_cpu(get_unaligned_le32(ptr));
+		addr = get_unaligned_le32(ptr);
 		ptr += sizeof(u32);
-		val = le16_to_cpu(get_unaligned_le16(ptr));
+		val = get_unaligned_le16(ptr);
 		ptr += sizeof(u16);
 		if (addr - addr_inc != 2)
 			err = s5k4ecgx_write(client, addr, val);
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 60a74d8d38d5..a3d7d0391302 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -353,7 +353,7 @@ static struct v4l2_rect s5k5baf_cis_rect = {
  *
  */
 static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw,
-			    size_t count, const u16 *data)
+			    size_t count, const __le16 *data)
 {
 	struct s5k5baf_fw *f;
 	u16 *d, i, *end;
@@ -421,6 +421,7 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr)
 {
 	struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
 	__be16 w, r;
+	u16 res;
 	struct i2c_msg msg[] = {
 		{ .addr = c->addr, .flags = 0,
 		  .len = 2, .buf = (u8 *)&w },
@@ -434,15 +435,15 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr)
 
 	w = cpu_to_be16(addr);
 	ret = i2c_transfer(c->adapter, msg, 2);
-	r = be16_to_cpu(r);
+	res = be16_to_cpu(r);
 
-	v4l2_dbg(3, debug, c, "i2c_read: 0x%04x : 0x%04x\n", addr, r);
+	v4l2_dbg(3, debug, c, "i2c_read: 0x%04x : 0x%04x\n", addr, res);
 
 	if (ret != 2) {
 		v4l2_err(c, "i2c_read: error during transfer (%d)\n", ret);
 		state->error = ret;
 	}
-	return r;
+	return res;
 }
 
 static void s5k5baf_i2c_write(struct s5k5baf *state, u16 addr, u16 val)
@@ -1037,7 +1038,7 @@ static int s5k5baf_load_setfile(struct s5k5baf *state)
 	}
 
 	ret = s5k5baf_fw_parse(&c->dev, &state->fw, fw->size / 2,
-			       (u16 *)fw->data);
+			       (__le16 *)fw->data);
 
 	release_firmware(fw);
 
@@ -1793,7 +1794,7 @@ static const struct v4l2_subdev_ops s5k5baf_subdev_ops = {
 
 static int s5k5baf_configure_gpios(struct s5k5baf *state)
 {
-	static const char const *name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" };
+	static const char * const name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" };
 	struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
 	struct s5k5baf_gpio *g = state->gpios;
 	int ret, i;
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
index 2851581e0061..b1c583239dab 100644
--- a/drivers/media/i2c/s5k6aa.c
+++ b/drivers/media/i2c/s5k6aa.c
@@ -348,7 +348,7 @@ static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
 	msg[1].buf = rbuf;
 
 	ret = i2c_transfer(client->adapter, msg, 2);
-	*val = be16_to_cpu(*((u16 *)rbuf));
+	*val = be16_to_cpu(*((__be16 *)rbuf));
 
 	v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
 
@@ -1161,17 +1161,21 @@ static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 	return ret;
 }
 
-static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-			   struct v4l2_subdev_crop *crop)
+static int s5k6aa_get_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_selection *sel)
 {
 	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
 	struct v4l2_rect *rect;
 
-	memset(crop->reserved, 0, sizeof(crop->reserved));
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	memset(sel->reserved, 0, sizeof(sel->reserved));
 
 	mutex_lock(&s5k6aa->lock);
-	rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
-	crop->rect = *rect;
+	rect = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
+	sel->r = *rect;
 	mutex_unlock(&s5k6aa->lock);
 
 	v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
@@ -1180,35 +1184,39 @@ static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 	return 0;
 }
 
-static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-			   struct v4l2_subdev_crop *crop)
+static int s5k6aa_set_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_selection *sel)
 {
 	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
 	struct v4l2_mbus_framefmt *mf;
 	unsigned int max_x, max_y;
 	struct v4l2_rect *crop_r;
 
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
 	mutex_lock(&s5k6aa->lock);
-	crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+	crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
 
-	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 		mf = &s5k6aa->preset->mbus_fmt;
 		s5k6aa->apply_crop = 1;
 	} else {
 		mf = v4l2_subdev_get_try_format(fh, 0);
 	}
-	v4l_bound_align_image(&crop->rect.width, mf->width,
+	v4l_bound_align_image(&sel->r.width, mf->width,
 			      S5K6AA_WIN_WIDTH_MAX, 1,
-			      &crop->rect.height, mf->height,
+			      &sel->r.height, mf->height,
 			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
 
-	max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1;
-	max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1;
+	max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1;
+	max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1;
 
-	crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x);
-	crop->rect.top  = clamp_t(unsigned int, crop->rect.top, 0, max_y);
+	sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x);
+	sel->r.top  = clamp_t(unsigned int, sel->r.top, 0, max_y);
 
-	*crop_r = crop->rect;
+	*crop_r = sel->r;
 
 	mutex_unlock(&s5k6aa->lock);
 
@@ -1224,8 +1232,8 @@ static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
 	.enum_frame_interval	= s5k6aa_enum_frame_interval,
 	.get_fmt		= s5k6aa_get_fmt,
 	.set_fmt		= s5k6aa_set_fmt,
-	.get_crop		= s5k6aa_get_crop,
-	.set_crop		= s5k6aa_set_crop,
+	.get_selection		= s5k6aa_get_selection,
+	.set_selection		= s5k6aa_set_selection,
 };
 
 static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index e40d9027df3d..e3348db56c46 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -14,14 +14,9 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
+#include <linux/device.h>
 #include <linux/gcd.h>
 #include <linux/lcm.h>
 #include <linux/module.h>
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index e8f035a50c76..b98d143b64e1 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -14,19 +14,11 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #ifndef SMIAPP_PLL_H
 #define SMIAPP_PLL_H
 
-#include <linux/device.h>
-
 /* CSI-2 or CCP-2 */
 #define SMIAPP_PLL_BUS_TYPE_CSI2				0x00
 #define SMIAPP_PLL_BUS_TYPE_PARALLEL				0x01
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 0df5070e73c7..d47eff5d3101 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -18,12 +18,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #include <linux/clk.h>
@@ -31,11 +25,13 @@
 #include <linux/device.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
+#include <linux/of_gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/smiapp.h>
 #include <linux/v4l2-mediabus.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-of.h>
 
 #include "smiapp.h"
 
@@ -523,14 +519,12 @@ static const struct v4l2_ctrl_ops smiapp_ctrl_ops = {
 static int smiapp_init_controls(struct smiapp_sensor *sensor)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
-		sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
-	unsigned int max, i;
 	int rval;
 
 	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12);
 	if (rval)
 		return rval;
+
 	sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
 
 	sensor->analog_gain = v4l2_ctrl_new_std(
@@ -576,21 +570,11 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
 				     ARRAY_SIZE(smiapp_test_patterns) - 1,
 				     0, 0, smiapp_test_patterns);
 
-	for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
-		int max_value = (1 << sensor->csi_format->width) - 1;
-		sensor->test_data[i] =
-			v4l2_ctrl_new_std(
-				&sensor->pixel_array->ctrl_handler,
-				&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i,
-				0, max_value, 1, max_value);
-	}
-
 	if (sensor->pixel_array->ctrl_handler.error) {
 		dev_err(&client->dev,
 			"pixel array controls initialization failed (%d)\n",
 			sensor->pixel_array->ctrl_handler.error);
-		rval = sensor->pixel_array->ctrl_handler.error;
-		goto error;
+		return sensor->pixel_array->ctrl_handler.error;
 	}
 
 	sensor->pixel_array->sd.ctrl_handler =
@@ -600,15 +584,9 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
 
 	rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
 	if (rval)
-		goto error;
-	sensor->src->ctrl_handler.lock = &sensor->mutex;
-
-	for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++);
+		return rval;
 
-	sensor->link_freq = v4l2_ctrl_new_int_menu(
-		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
-		V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
-		__ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock);
+	sensor->src->ctrl_handler.lock = &sensor->mutex;
 
 	sensor->pixel_rate_csi = v4l2_ctrl_new_std(
 		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
@@ -618,20 +596,41 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
 		dev_err(&client->dev,
 			"src controls initialization failed (%d)\n",
 			sensor->src->ctrl_handler.error);
-		rval = sensor->src->ctrl_handler.error;
-		goto error;
+		return sensor->src->ctrl_handler.error;
 	}
 
-	sensor->src->sd.ctrl_handler =
-		&sensor->src->ctrl_handler;
+	sensor->src->sd.ctrl_handler = &sensor->src->ctrl_handler;
 
 	return 0;
+}
+
+/*
+ * For controls that require information on available media bus codes
+ * and linke frequencies.
+ */
+static int smiapp_init_late_controls(struct smiapp_sensor *sensor)
+{
+	unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
+		sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
+	unsigned int max, i;
 
-error:
-	v4l2_ctrl_handler_free(&sensor->pixel_array->ctrl_handler);
-	v4l2_ctrl_handler_free(&sensor->src->ctrl_handler);
+	for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
+		int max_value = (1 << sensor->csi_format->width) - 1;
 
-	return rval;
+		sensor->test_data[i] = v4l2_ctrl_new_std(
+				&sensor->pixel_array->ctrl_handler,
+				&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i,
+				0, max_value, 1, max_value);
+	}
+
+	for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++);
+
+	sensor->link_freq = v4l2_ctrl_new_int_menu(
+		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
+		__ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock);
+
+	return sensor->src->ctrl_handler.error;
 }
 
 static void smiapp_free_controls(struct smiapp_sensor *sensor)
@@ -1487,7 +1486,7 @@ static int smiapp_start_streaming(struct smiapp_sensor *sensor)
 	if (rval < 0)
 		goto out;
 
-	if ((sensor->flash_capability &
+	if ((sensor->limits[SMIAPP_LIMIT_FLASH_MODE_CAPABILITY] &
 	     (SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
 	      SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) &&
 	    sensor->platform_data->strobe_setup != NULL &&
@@ -2338,10 +2337,9 @@ static DEVICE_ATTR(ident, S_IRUGO, smiapp_sysfs_ident_read, NULL);
  * V4L2 subdev core operations
  */
 
-static int smiapp_identify_module(struct v4l2_subdev *subdev)
+static int smiapp_identify_module(struct smiapp_sensor *sensor)
 {
-	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	struct smiapp_module_info *minfo = &sensor->minfo;
 	unsigned int i;
 	int rval = 0;
@@ -2464,8 +2462,6 @@ static int smiapp_identify_module(struct v4l2_subdev *subdev)
 		minfo->name, minfo->manufacturer_id, minfo->model_id,
 		minfo->revision_number_major);
 
-	strlcpy(subdev->name, sensor->minfo.name, sizeof(subdev->name));
-
 	return 0;
 }
 
@@ -2473,13 +2469,71 @@ static const struct v4l2_subdev_ops smiapp_ops;
 static const struct v4l2_subdev_internal_ops smiapp_internal_ops;
 static const struct media_entity_operations smiapp_entity_ops;
 
-static int smiapp_registered(struct v4l2_subdev *subdev)
+static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
 {
-	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	struct smiapp_subdev *ssds[] = {
+		sensor->scaler,
+		sensor->binner,
+		sensor->pixel_array,
+	};
+	unsigned int i;
+	int rval;
+
+	for (i = 0; i < SMIAPP_SUBDEVS - 1; i++) {
+		struct smiapp_subdev *this = ssds[i + 1];
+		struct smiapp_subdev *last = ssds[i];
+
+		if (!last)
+			continue;
+
+		rval = media_entity_init(&this->sd.entity,
+					 this->npads, this->pads, 0);
+		if (rval) {
+			dev_err(&client->dev,
+				"media_entity_init failed\n");
+			return rval;
+		}
+
+		rval = media_entity_create_link(&this->sd.entity,
+						this->source_pad,
+						&last->sd.entity,
+						last->sink_pad,
+						MEDIA_LNK_FL_ENABLED |
+						MEDIA_LNK_FL_IMMUTABLE);
+		if (rval) {
+			dev_err(&client->dev,
+				"media_entity_create_link failed\n");
+			return rval;
+		}
+
+		rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
+						   &this->sd);
+		if (rval) {
+			dev_err(&client->dev,
+				"v4l2_device_register_subdev failed\n");
+			return rval;
+		}
+	}
+
+	return 0;
+}
+
+static void smiapp_cleanup(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+
+	device_remove_file(&client->dev, &dev_attr_nvm);
+	device_remove_file(&client->dev, &dev_attr_ident);
+
+	smiapp_free_controls(sensor);
+}
+
+static int smiapp_init(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	struct smiapp_pll *pll = &sensor->pll;
 	struct smiapp_subdev *last = NULL;
-	u32 tmp;
 	unsigned int i;
 	int rval;
 
@@ -2490,7 +2544,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	}
 
 	if (!sensor->platform_data->set_xclk) {
-		sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk");
+		sensor->ext_clk = devm_clk_get(&client->dev, NULL);
 		if (IS_ERR(sensor->ext_clk)) {
 			dev_err(&client->dev, "could not get clock\n");
 			return PTR_ERR(sensor->ext_clk);
@@ -2522,7 +2576,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	if (rval)
 		return -ENODEV;
 
-	rval = smiapp_identify_module(subdev);
+	rval = smiapp_identify_module(sensor);
 	if (rval) {
 		rval = -ENODEV;
 		goto out_power_off;
@@ -2602,13 +2656,13 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 		if (sensor->nvm == NULL) {
 			dev_err(&client->dev, "nvm buf allocation failed\n");
 			rval = -ENOMEM;
-			goto out_ident_release;
+			goto out_cleanup;
 		}
 
 		if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
 			dev_err(&client->dev, "sysfs nvm entry failed\n");
 			rval = -EBUSY;
-			goto out_ident_release;
+			goto out_cleanup;
 		}
 	}
 
@@ -2643,18 +2697,11 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
 	pll->csi2.lanes = sensor->platform_data->lanes;
 	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
-	pll->flags = smiapp_call_quirk(sensor, pll_flags);
 	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
 	/* Profile 0 sensors have no separate OP clock branch. */
 	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
 		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
 
-	rval = smiapp_get_mbus_formats(sensor);
-	if (rval) {
-		rval = -ENODEV;
-		goto out_nvm_release;
-	}
-
 	for (i = 0; i < SMIAPP_SUBDEVS; i++) {
 		struct {
 			struct smiapp_subdev *ssd;
@@ -2711,34 +2758,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 		this->sd.owner = THIS_MODULE;
 		v4l2_set_subdevdata(&this->sd, client);
 
-		rval = media_entity_init(&this->sd.entity,
-					 this->npads, this->pads, 0);
-		if (rval) {
-			dev_err(&client->dev,
-				"media_entity_init failed\n");
-			goto out_nvm_release;
-		}
-
-		rval = media_entity_create_link(&this->sd.entity,
-						this->source_pad,
-						&last->sd.entity,
-						last->sink_pad,
-						MEDIA_LNK_FL_ENABLED |
-						MEDIA_LNK_FL_IMMUTABLE);
-		if (rval) {
-			dev_err(&client->dev,
-				"media_entity_create_link failed\n");
-			goto out_nvm_release;
-		}
-
-		rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
-						   &this->sd);
-		if (rval) {
-			dev_err(&client->dev,
-				"v4l2_device_register_subdev failed\n");
-			goto out_nvm_release;
-		}
-
 		last = this;
 	}
 
@@ -2750,40 +2769,66 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	smiapp_read_frame_fmt(sensor);
 	rval = smiapp_init_controls(sensor);
 	if (rval < 0)
-		goto out_nvm_release;
+		goto out_cleanup;
+
+	rval = smiapp_call_quirk(sensor, init);
+	if (rval)
+		goto out_cleanup;
+
+	rval = smiapp_get_mbus_formats(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_cleanup;
+	}
+
+	rval = smiapp_init_late_controls(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_cleanup;
+	}
 
 	mutex_lock(&sensor->mutex);
 	rval = smiapp_update_mode(sensor);
 	mutex_unlock(&sensor->mutex);
 	if (rval) {
 		dev_err(&client->dev, "update mode failed\n");
-		goto out_nvm_release;
+		goto out_cleanup;
 	}
 
 	sensor->streaming = false;
 	sensor->dev_init_done = true;
 
-	/* check flash capability */
-	rval = smiapp_read(sensor, SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, &tmp);
-	sensor->flash_capability = tmp;
-	if (rval)
-		goto out_nvm_release;
-
 	smiapp_power_off(sensor);
 
 	return 0;
 
-out_nvm_release:
-	device_remove_file(&client->dev, &dev_attr_nvm);
-
-out_ident_release:
-	device_remove_file(&client->dev, &dev_attr_ident);
+out_cleanup:
+	smiapp_cleanup(sensor);
 
 out_power_off:
 	smiapp_power_off(sensor);
 	return rval;
 }
 
+static int smiapp_registered(struct v4l2_subdev *subdev)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	int rval;
+
+	if (!client->dev.of_node) {
+		rval = smiapp_init(sensor);
+		if (rval)
+			return rval;
+	}
+
+	rval = smiapp_register_subdevs(sensor);
+	if (rval)
+		smiapp_cleanup(sensor);
+
+	return rval;
+}
+
 static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
 	struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
@@ -2927,19 +2972,125 @@ static int smiapp_resume(struct device *dev)
 
 #endif /* CONFIG_PM */
 
+static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
+{
+	struct smiapp_platform_data *pdata;
+	struct v4l2_of_endpoint bus_cfg;
+	struct device_node *ep;
+	struct property *prop;
+	__be32 *val;
+	uint32_t asize;
+#ifdef CONFIG_OF
+	unsigned int i;
+#endif
+	int rval;
+
+	if (!dev->of_node)
+		return dev->platform_data;
+
+	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
+	if (!ep)
+		return NULL;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		rval = -ENOMEM;
+		goto out_err;
+	}
+
+	v4l2_of_parse_endpoint(ep, &bus_cfg);
+
+	switch (bus_cfg.bus_type) {
+	case V4L2_MBUS_CSI2:
+		pdata->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2;
+		break;
+		/* FIXME: add CCP2 support. */
+	default:
+		rval = -EINVAL;
+		goto out_err;
+	}
+
+	pdata->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
+	dev_dbg(dev, "lanes %u\n", pdata->lanes);
+
+	/* xshutdown GPIO is optional */
+	pdata->xshutdown = of_get_named_gpio(dev->of_node, "reset-gpios", 0);
+
+	/* NVM size is not mandatory */
+	of_property_read_u32(dev->of_node, "nokia,nvm-size",
+				    &pdata->nvm_size);
+
+	rval = of_property_read_u32(dev->of_node, "clock-frequency",
+				    &pdata->ext_clk);
+	if (rval) {
+		dev_warn(dev, "can't get clock-frequency\n");
+		goto out_err;
+	}
+
+	dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown,
+		pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode);
+
+	rval = of_get_property(
+		dev->of_node, "link-frequencies", &asize) ? 0 : -ENOENT;
+	if (rval) {
+		dev_warn(dev, "can't get link-frequencies array size\n");
+		goto out_err;
+	}
+
+	pdata->op_sys_clock = devm_kzalloc(dev, asize, GFP_KERNEL);
+	if (!pdata->op_sys_clock) {
+		rval = -ENOMEM;
+		goto out_err;
+	}
+
+	asize /= sizeof(*pdata->op_sys_clock);
+	/*
+	 * Read a 64-bit array --- this will be replaced with a
+	 * of_property_read_u64_array() once it's merged.
+	 */
+	prop = of_find_property(dev->of_node, "link-frequencies", NULL);
+	if (!prop)
+		goto out_err;
+	if (!prop->value)
+		goto out_err;
+	if (asize * sizeof(*pdata->op_sys_clock) > prop->length)
+		goto out_err;
+	val = prop->value;
+	if (IS_ERR(val))
+		goto out_err;
+
+#ifdef CONFIG_OF
+	for (i = 0; i < asize; i++)
+		pdata->op_sys_clock[i] = of_read_number(val + i * 2, 2);
+#endif
+
+	for (; asize > 0; asize--)
+		dev_dbg(dev, "freq %d: %lld\n", asize - 1,
+			pdata->op_sys_clock[asize - 1]);
+
+	of_node_put(ep);
+	return pdata;
+
+out_err:
+	of_node_put(ep);
+	return NULL;
+}
+
 static int smiapp_probe(struct i2c_client *client,
 			const struct i2c_device_id *devid)
 {
 	struct smiapp_sensor *sensor;
+	struct smiapp_platform_data *pdata = smiapp_get_pdata(&client->dev);
+	int rval;
 
-	if (client->dev.platform_data == NULL)
+	if (pdata == NULL)
 		return -ENODEV;
 
 	sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
 	if (sensor == NULL)
 		return -ENOMEM;
 
-	sensor->platform_data = client->dev.platform_data;
+	sensor->platform_data = pdata;
 	mutex_init(&sensor->mutex);
 	mutex_init(&sensor->power_mutex);
 	sensor->src = &sensor->ssds[sensor->ssds_used];
@@ -2950,8 +3101,27 @@ static int smiapp_probe(struct i2c_client *client,
 	sensor->src->sensor = sensor;
 
 	sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
-	return media_entity_init(&sensor->src->sd.entity, 2,
+	rval = media_entity_init(&sensor->src->sd.entity, 2,
 				 sensor->src->pads, 0);
+	if (rval < 0)
+		return rval;
+
+	if (client->dev.of_node) {
+		rval = smiapp_init(sensor);
+		if (rval)
+			goto out_media_entity_cleanup;
+	}
+
+	rval = v4l2_async_register_subdev(&sensor->src->sd);
+	if (rval < 0)
+		goto out_media_entity_cleanup;
+
+	return 0;
+
+out_media_entity_cleanup:
+	media_entity_cleanup(&sensor->src->sd.entity);
+
+	return rval;
 }
 
 static int smiapp_remove(struct i2c_client *client)
@@ -2960,6 +3130,8 @@ static int smiapp_remove(struct i2c_client *client)
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
 	unsigned int i;
 
+	v4l2_async_unregister_subdev(subdev);
+
 	if (sensor->power_count) {
 		if (gpio_is_valid(sensor->platform_data->xshutdown))
 			gpio_set_value(sensor->platform_data->xshutdown, 0);
@@ -2970,19 +3142,20 @@ static int smiapp_remove(struct i2c_client *client)
 		sensor->power_count = 0;
 	}
 
-	device_remove_file(&client->dev, &dev_attr_ident);
-	if (sensor->nvm)
-		device_remove_file(&client->dev, &dev_attr_nvm);
-
 	for (i = 0; i < sensor->ssds_used; i++) {
 		v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
 		media_entity_cleanup(&sensor->ssds[i].sd.entity);
 	}
-	smiapp_free_controls(sensor);
+	smiapp_cleanup(sensor);
 
 	return 0;
 }
 
+static const struct of_device_id smiapp_of_table[] = {
+	{ .compatible = "nokia,smia" },
+	{ },
+};
+
 static const struct i2c_device_id smiapp_id_table[] = {
 	{ SMIAPP_NAME, 0 },
 	{ },
@@ -2996,6 +3169,7 @@ static const struct dev_pm_ops smiapp_pm_ops = {
 
 static struct i2c_driver smiapp_i2c_driver = {
 	.driver	= {
+		.of_match_table = smiapp_of_table,
 		.name = SMIAPP_NAME,
 		.pm = &smiapp_pm_ops,
 	},
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.c b/drivers/media/i2c/smiapp/smiapp-limits.c
index 847cb235e198..784b114d3f8b 100644
--- a/drivers/media/i2c/smiapp/smiapp-limits.c
+++ b/drivers/media/i2c/smiapp/smiapp-limits.c
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #include "smiapp.h"
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.h b/drivers/media/i2c/smiapp/smiapp-limits.h
index 343e9c3827fc..b20124862a14 100644
--- a/drivers/media/i2c/smiapp/smiapp-limits.h
+++ b/drivers/media/i2c/smiapp/smiapp-limits.h
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY			0
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index e0bee8752122..abf9ea7a0fb7 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #include <linux/delay.h>
@@ -220,9 +214,11 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
 	return smiapp_write_8(sensor, 0x3328, 0x80);
 }
 
-static unsigned long jt8ev1_pll_flags(struct smiapp_sensor *sensor)
+static int jt8ev1_init(struct smiapp_sensor *sensor)
 {
-	return SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+	sensor->pll.flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+
+	return 0;
 }
 
 const struct smiapp_quirk smiapp_jt8ev1_quirk = {
@@ -230,7 +226,7 @@ const struct smiapp_quirk smiapp_jt8ev1_quirk = {
 	.post_poweron = jt8ev1_post_poweron,
 	.pre_streamon = jt8ev1_pre_streamon,
 	.post_streamoff = jt8ev1_post_streamoff,
-	.pll_flags = jt8ev1_pll_flags,
+	.init = jt8ev1_init,
 };
 
 static int tcm8500md_limits(struct smiapp_sensor *sensor)
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 46e9ea8bfa08..dac5566a2f7a 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #ifndef __SMIAPP_QUIRK__
@@ -35,6 +29,9 @@ struct smiapp_sensor;
  * @post_poweron: Called always after the sensor has been fully powered on.
  * @pre_streamon: Called just before streaming is enabled.
  * @post_streamon: Called right after stopping streaming.
+ * @pll_flags: Return flags for the PLL calculator.
+ * @init: Quirk initialisation, called the last in probe(). This is
+ *	  also appropriate for adding sensor specific controls, for instance.
  * @reg_access: Register access quirk. The quirk may divert the access
  *		to another register, or no register at all.
  *
@@ -53,6 +50,7 @@ struct smiapp_quirk {
 	int (*pre_streamon)(struct smiapp_sensor *sensor);
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
 	unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
+	int (*init)(struct smiapp_sensor *sensor);
 	int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg,
 			  u32 *val);
 	unsigned long flags;
@@ -74,14 +72,14 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
 		.val = _val,		\
 	}
 
-#define smiapp_call_quirk(_sensor, _quirk, ...)				\
-	(_sensor->minfo.quirk &&					\
-	 _sensor->minfo.quirk->_quirk ?					\
-	 _sensor->minfo.quirk->_quirk(_sensor, ##__VA_ARGS__) : 0)
+#define smiapp_call_quirk(sensor, _quirk, ...)				\
+	((sensor)->minfo.quirk &&					\
+	 (sensor)->minfo.quirk->_quirk ?				\
+	 (sensor)->minfo.quirk->_quirk(sensor, ##__VA_ARGS__) : 0)
 
-#define smiapp_needs_quirk(_sensor, _quirk)		\
-	(_sensor->minfo.quirk ?				\
-	 _sensor->minfo.quirk->flags & _quirk : 0)
+#define smiapp_needs_quirk(sensor, _quirk)		\
+	((sensor)->minfo.quirk ?			\
+	 (sensor)->minfo.quirk->flags & _quirk : 0)
 
 extern const struct smiapp_quirk smiapp_jt8ev1_quirk;
 extern const struct smiapp_quirk smiapp_imx125es_quirk;
diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
index c488ef028074..f928d4cc8e26 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 #define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r))
 #define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r))
diff --git a/drivers/media/i2c/smiapp/smiapp-reg.h b/drivers/media/i2c/smiapp/smiapp-reg.h
index b0dcbb8fa5e2..4c8b40614969 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg.h
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #ifndef __SMIAPP_REG_H_
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index a2098007fb70..6b6c20b61397 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #include <linux/delay.h>
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index 35521125a2cc..6dd0e499c845 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #ifndef SMIAPP_REGS_H
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index f88f8ec344d3..ed010a8a49d7 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -14,12 +14,6 @@
  * 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 St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
  */
 
 #ifndef __SMIAPP_PRIV_H_
@@ -222,7 +216,6 @@ struct smiapp_sensor {
 	u8 scaling_mode;
 
 	u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
-	u8 flash_capability;
 	u8 frame_skip;
 
 	int power_count;
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index 6f2dd9093d94..1fdce2f6f880 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -25,6 +25,7 @@
 #include <media/v4l2-clk.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-image-sizes.h>
 
 #define VAL_SET(x, mask, rshift, lshift)  \
 		((((x) >> rshift) & mask) << lshift)
@@ -268,33 +269,10 @@ struct regval_list {
 	u8 value;
 };
 
-/* Supported resolutions */
-enum ov2640_width {
-	W_QCIF	= 176,
-	W_QVGA	= 320,
-	W_CIF	= 352,
-	W_VGA	= 640,
-	W_SVGA	= 800,
-	W_XGA	= 1024,
-	W_SXGA	= 1280,
-	W_UXGA	= 1600,
-};
-
-enum ov2640_height {
-	H_QCIF	= 144,
-	H_QVGA	= 240,
-	H_CIF	= 288,
-	H_VGA	= 480,
-	H_SVGA	= 600,
-	H_XGA	= 768,
-	H_SXGA	= 1024,
-	H_UXGA	= 1200,
-};
-
 struct ov2640_win_size {
 	char				*name;
-	enum ov2640_width		width;
-	enum ov2640_height		height;
+	u32				width;
+	u32				height;
 	const struct regval_list	*regs;
 };
 
@@ -495,17 +473,17 @@ static const struct regval_list ov2640_init_regs[] = {
 static const struct regval_list ov2640_size_change_preamble_regs[] = {
 	{ BANK_SEL, BANK_SEL_DSP },
 	{ RESET, RESET_DVP },
-	{ HSIZE8, HSIZE8_SET(W_UXGA) },
-	{ VSIZE8, VSIZE8_SET(H_UXGA) },
+	{ HSIZE8, HSIZE8_SET(UXGA_WIDTH) },
+	{ VSIZE8, VSIZE8_SET(UXGA_HEIGHT) },
 	{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
 		 CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
-	{ HSIZE, HSIZE_SET(W_UXGA) },
-	{ VSIZE, VSIZE_SET(H_UXGA) },
+	{ HSIZE, HSIZE_SET(UXGA_WIDTH) },
+	{ VSIZE, VSIZE_SET(UXGA_HEIGHT) },
 	{ XOFFL, XOFFL_SET(0) },
 	{ YOFFL, YOFFL_SET(0) },
-	{ VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) |
+	{ VHYX, VHYX_HSIZE_SET(UXGA_WIDTH) | VHYX_VSIZE_SET(UXGA_HEIGHT) |
 		VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},
-	{ TEST, TEST_HSIZE_SET(W_UXGA) },
+	{ TEST, TEST_HSIZE_SET(UXGA_WIDTH) },
 	ENDMARKER,
 };
 
@@ -519,45 +497,45 @@ static const struct regval_list ov2640_size_change_preamble_regs[] = {
 	{ RESET, 0x00}
 
 static const struct regval_list ov2640_qcif_regs[] = {
-	PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4),
+	PER_SIZE_REG_SEQ(QCIF_WIDTH, QCIF_HEIGHT, 3, 3, 4),
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_qvga_regs[] = {
-	PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4),
+	PER_SIZE_REG_SEQ(QVGA_WIDTH, QVGA_HEIGHT, 2, 2, 4),
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_cif_regs[] = {
-	PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8),
+	PER_SIZE_REG_SEQ(CIF_WIDTH, CIF_HEIGHT, 2, 2, 8),
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_vga_regs[] = {
-	PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2),
+	PER_SIZE_REG_SEQ(VGA_WIDTH, VGA_HEIGHT, 0, 0, 2),
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_svga_regs[] = {
-	PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2),
+	PER_SIZE_REG_SEQ(SVGA_WIDTH, SVGA_HEIGHT, 1, 1, 2),
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_xga_regs[] = {
-	PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2),
+	PER_SIZE_REG_SEQ(XGA_WIDTH, XGA_HEIGHT, 0, 0, 2),
 	{ CTRLI,    0x00},
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_sxga_regs[] = {
-	PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2),
+	PER_SIZE_REG_SEQ(SXGA_WIDTH, SXGA_HEIGHT, 0, 0, 2),
 	{ CTRLI,    0x00},
 	{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
 	ENDMARKER,
 };
 
 static const struct regval_list ov2640_uxga_regs[] = {
-	PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0),
+	PER_SIZE_REG_SEQ(UXGA_WIDTH, UXGA_HEIGHT, 0, 0, 0),
 	{ CTRLI,    0x00},
 	{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
 	ENDMARKER,
@@ -567,14 +545,14 @@ static const struct regval_list ov2640_uxga_regs[] = {
 	{.name = n, .width = w , .height = h, .regs = r }
 
 static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
-	OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs),
-	OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs),
-	OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs),
-	OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs),
-	OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs),
-	OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs),
-	OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs),
-	OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs),
+	OV2640_SIZE("QCIF", QCIF_WIDTH, QCIF_HEIGHT, ov2640_qcif_regs),
+	OV2640_SIZE("QVGA", QVGA_WIDTH, QVGA_HEIGHT, ov2640_qvga_regs),
+	OV2640_SIZE("CIF", CIF_WIDTH, CIF_HEIGHT, ov2640_cif_regs),
+	OV2640_SIZE("VGA", VGA_WIDTH, VGA_HEIGHT, ov2640_vga_regs),
+	OV2640_SIZE("SVGA", SVGA_WIDTH, SVGA_HEIGHT, ov2640_svga_regs),
+	OV2640_SIZE("XGA", XGA_WIDTH, XGA_HEIGHT, ov2640_xga_regs),
+	OV2640_SIZE("SXGA", SXGA_WIDTH, SXGA_HEIGHT, ov2640_sxga_regs),
+	OV2640_SIZE("UXGA", UXGA_WIDTH, UXGA_HEIGHT, ov2640_uxga_regs),
 };
 
 /*
@@ -867,7 +845,7 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd,
 	struct ov2640_priv *priv = to_ov2640(client);
 
 	if (!priv->win) {
-		u32 width = W_SVGA, height = H_SVGA;
+		u32 width = SVGA_WIDTH, height = SVGA_HEIGHT;
 		priv->win = ov2640_select_win(&width, &height);
 		priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
 	}
@@ -954,8 +932,8 @@ static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
 	a->c.left	= 0;
 	a->c.top	= 0;
-	a->c.width	= W_UXGA;
-	a->c.height	= H_UXGA;
+	a->c.width	= UXGA_WIDTH;
+	a->c.height	= UXGA_HEIGHT;
 	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
 	return 0;
@@ -965,8 +943,8 @@ static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
 	a->bounds.left			= 0;
 	a->bounds.top			= 0;
-	a->bounds.width			= W_UXGA;
-	a->bounds.height		= H_UXGA;
+	a->bounds.width			= UXGA_WIDTH;
+	a->bounds.height		= UXGA_HEIGHT;
 	a->defrect			= a->bounds;
 	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	a->pixelaspect.numerator	= 1;
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index 656d889c1c79..4ebd329d7b42 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -58,21 +58,11 @@ static inline struct ths8200_state *to_state(struct v4l2_subdev *sd)
 	return container_of(sd, struct ths8200_state, sd);
 }
 
-static inline unsigned hblanking(const struct v4l2_bt_timings *t)
-{
-	return V4L2_DV_BT_BLANKING_WIDTH(t);
-}
-
 static inline unsigned htotal(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_FRAME_WIDTH(t);
 }
 
-static inline unsigned vblanking(const struct v4l2_bt_timings *t)
-{
-	return V4L2_DV_BT_BLANKING_HEIGHT(t);
-}
-
 static inline unsigned vtotal(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_FRAME_HEIGHT(t);
diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig
index aa05ad3c1ccb..7693487e2f63 100644
--- a/drivers/media/mmc/siano/Kconfig
+++ b/drivers/media/mmc/siano/Kconfig
@@ -6,6 +6,8 @@ config SMS_SDIO_DRV
 	tristate "Siano SMS1xxx based MDTV via SDIO interface"
 	depends on DVB_CORE && HAS_DMA
 	depends on MMC
+	depends on !RC_CORE || RC_CORE
 	select MEDIA_COMMON_OPTIONS
+	select SMS_SIANO_MDTV
 	---help---
 	  Choose if you would like to have Siano's support for SDIO interface
diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig
index 61d09e010814..4a93f6ded100 100644
--- a/drivers/media/pci/bt8xx/Kconfig
+++ b/drivers/media/pci/bt8xx/Kconfig
@@ -2,15 +2,17 @@ config VIDEO_BT848
 	tristate "BT848 Video For Linux"
 	depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
 	select I2C_ALGOBIT
-	select VIDEO_BTCX
 	select VIDEOBUF_DMA_SG
 	depends on RC_CORE
+	depends on MEDIA_RADIO_SUPPORT
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
+	select RADIO_ADAPTERS
+	select RADIO_TEA575X
 	---help---
 	  Support for BT848 based frame grabber/overlay boards. This includes
 	  the Miro, Hauppauge and STB boards. Please read the material in
diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile
index f9fe7c4e7d53..2d4c3dd88be1 100644
--- a/drivers/media/pci/bt8xx/Makefile
+++ b/drivers/media/pci/bt8xx/Makefile
@@ -1,6 +1,6 @@
 bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
 		       bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
-		       bttv-input.o bttv-audio-hook.o
+		       bttv-input.o bttv-audio-hook.o btcx-risc.o
 
 obj-$(CONFIG_VIDEO_BT848) += bttv.o
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c
index 11765835d7b2..0939d399b774 100644
--- a/drivers/media/pci/bt8xx/bt878.c
+++ b/drivers/media/pci/bt8xx/bt878.c
@@ -590,9 +590,3 @@ module_init(bt878_init_module);
 module_exit(bt878_cleanup_module);
 
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/btcx-risc.c b/drivers/media/pci/bt8xx/btcx-risc.c
index ac1b2687a20d..00f0880b6d66 100644
--- a/drivers/media/common/btcx-risc.c
+++ b/drivers/media/pci/bt8xx/btcx-risc.c
@@ -32,13 +32,9 @@
 
 #include "btcx-risc.h"
 
-MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
+static unsigned int btcx_debug;
+module_param(btcx_debug, int, 0644);
+MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)");
 
 /* ---------------------------------------------------------- */
 /* allocate/free risc memory                                  */
@@ -50,7 +46,7 @@ void btcx_riscmem_free(struct pci_dev *pci,
 {
 	if (NULL == risc->cpu)
 		return;
-	if (debug) {
+	if (btcx_debug) {
 		memcnt--;
 		printk("btcx: riscmem free [%d] dma=%lx\n",
 		       memcnt, (unsigned long)risc->dma);
@@ -75,7 +71,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
 		risc->cpu  = cpu;
 		risc->dma  = dma;
 		risc->size = size;
-		if (debug) {
+		if (btcx_debug) {
 			memcnt++;
 			printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
 			       memcnt, (unsigned long)dma, cpu, size);
@@ -141,7 +137,7 @@ btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int m
 	dx = nx - win->left;
 	win->left  = nx;
 	win->width = nw;
-	if (debug)
+	if (btcx_debug)
 		printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
 		       win->width, win->height, win->left, win->top, dx);
 
@@ -153,7 +149,7 @@ btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int m
 			nw += mask+1;
 		clips[i].c.left  = nx;
 		clips[i].c.width = nw;
-		if (debug)
+		if (btcx_debug)
 			printk(KERN_DEBUG "btcx:   clip align %dx%d+%d+%d\n",
 			       clips[i].c.width, clips[i].c.height,
 			       clips[i].c.left, clips[i].c.top);
@@ -234,7 +230,7 @@ btcx_calc_skips(int line, int width, int *maxy,
 	*nskips = skip;
 	*maxy = maxline;
 
-	if (debug) {
+	if (btcx_debug) {
 		printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
 		for (skip = 0; skip < *nskips; skip++) {
 			printk(" %d-%d",skips[skip].start,skips[skip].end);
@@ -242,19 +238,3 @@ btcx_calc_skips(int line, int width, int *maxy,
 		printk("\n");
 	}
 }
-
-/* ---------------------------------------------------------- */
-
-EXPORT_SYMBOL(btcx_riscmem_alloc);
-EXPORT_SYMBOL(btcx_riscmem_free);
-
-EXPORT_SYMBOL(btcx_screen_clips);
-EXPORT_SYMBOL(btcx_align);
-EXPORT_SYMBOL(btcx_sort_clips);
-EXPORT_SYMBOL(btcx_calc_skips);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/btcx-risc.h b/drivers/media/pci/bt8xx/btcx-risc.h
new file mode 100644
index 000000000000..1ed7a000160a
--- /dev/null
+++ b/drivers/media/pci/bt8xx/btcx-risc.h
@@ -0,0 +1,26 @@
+struct btcx_riscmem {
+	unsigned int   size;
+	__le32         *cpu;
+	__le32         *jmp;
+	dma_addr_t     dma;
+};
+
+struct btcx_skiplist {
+	int start;
+	int end;
+};
+
+int  btcx_riscmem_alloc(struct pci_dev *pci,
+			struct btcx_riscmem *risc,
+			unsigned int size);
+void btcx_riscmem_free(struct pci_dev *pci,
+		       struct btcx_riscmem *risc);
+
+int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+		      struct v4l2_clip *clips, unsigned int n);
+int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
+	       unsigned int n, int mask);
+void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
+void btcx_calc_skips(int line, int width, int *maxy,
+		     struct btcx_skiplist *skips, unsigned int *nskips,
+		     const struct v4l2_clip *clips, unsigned int nclips);
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index 41055606b969..4654fb65ca21 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -84,8 +84,7 @@ static void gv800s_init(struct bttv *btv);
 static void td3116_muxsel(struct bttv *btv, unsigned int input);
 
 static int terratec_active_radio_upgrade(struct bttv *btv);
-static int tea5757_read(struct bttv *btv);
-static int tea5757_write(struct bttv *btv, int value);
+static int tea575x_init(struct bttv *btv);
 static void identify_by_eeprom(struct bttv *btv,
 			       unsigned char eeprom_data[256]);
 static int pvr_boot(struct bttv *btv);
@@ -3085,12 +3084,12 @@ static void miro_pinnacle_gpio(struct bttv *btv)
 		if (0 == (gpio & 0x20)) {
 			btv->has_radio = 1;
 			if (!miro_fmtuner[id]) {
-				btv->has_matchbox = 1;
-				btv->mbox_we    = (1<<6);
-				btv->mbox_most  = (1<<7);
-				btv->mbox_clk   = (1<<8);
-				btv->mbox_data  = (1<<9);
-				btv->mbox_mask  = (1<<6)|(1<<7)|(1<<8)|(1<<9);
+				btv->has_tea575x = 1;
+				btv->tea_gpio.wren = 6;
+				btv->tea_gpio.most = 7;
+				btv->tea_gpio.clk  = 8;
+				btv->tea_gpio.data = 9;
+				tea575x_init(btv);
 			}
 		} else {
 			btv->has_radio = 0;
@@ -3104,7 +3103,7 @@ static void miro_pinnacle_gpio(struct bttv *btv)
 		pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
 			btv->c.nr, id+1, btv->tuner_type,
 			!btv->has_radio ? "no" :
-			(btv->has_matchbox ? "matchbox" : "fmtuner"),
+			(btv->has_tea575x ? "tea575x" : "fmtuner"),
 			(-1 == msp) ? "no" : "yes");
 	} else {
 		/* new cards with microtune tuner */
@@ -3382,12 +3381,12 @@ void bttv_init_card2(struct bttv *btv)
 		break;
 	case BTTV_BOARD_VHX:
 		btv->has_radio    = 1;
-		btv->has_matchbox = 1;
-		btv->mbox_we      = 0x20;
-		btv->mbox_most    = 0;
-		btv->mbox_clk     = 0x08;
-		btv->mbox_data    = 0x10;
-		btv->mbox_mask    = 0x38;
+		btv->has_tea575x  = 1;
+		btv->tea_gpio.wren = 5;
+		btv->tea_gpio.most = 6;
+		btv->tea_gpio.clk  = 3;
+		btv->tea_gpio.data = 4;
+		tea575x_init(btv);
 		break;
 	case BTTV_BOARD_VOBIS_BOOSTAR:
 	case BTTV_BOARD_TERRATV:
@@ -3745,33 +3744,112 @@ static void hauppauge_eeprom(struct bttv *btv)
 		btv->radio_uses_msp_demodulator = 1;
 }
 
-static int terratec_active_radio_upgrade(struct bttv *btv)
+/* ----------------------------------------------------------------------- */
+
+static void bttv_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
+{
+	struct bttv *btv = tea->private_data;
+	struct bttv_tea575x_gpio gpio = btv->tea_gpio;
+	u16 val = 0;
+
+	val |= (pins & TEA575X_DATA) ? (1 << gpio.data) : 0;
+	val |= (pins & TEA575X_CLK)  ? (1 << gpio.clk)  : 0;
+	val |= (pins & TEA575X_WREN) ? (1 << gpio.wren) : 0;
+
+	gpio_bits((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren), val);
+	if (btv->mbox_ior) {
+		/* IOW and CSEL active */
+		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+		udelay(5);
+		/* all inactive */
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+	}
+}
+
+static u8 bttv_tea575x_get_pins(struct snd_tea575x *tea)
+{
+	struct bttv *btv = tea->private_data;
+	struct bttv_tea575x_gpio gpio = btv->tea_gpio;
+	u8 ret = 0;
+	u16 val;
+
+	if (btv->mbox_ior) {
+		/* IOR and CSEL active */
+		gpio_bits(btv->mbox_ior | btv->mbox_csel, 0);
+		udelay(5);
+	}
+	val = gpio_read();
+	if (btv->mbox_ior) {
+		/* all inactive */
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+	}
+
+	if (val & (1 << gpio.data))
+		ret |= TEA575X_DATA;
+	if (val & (1 << gpio.most))
+		ret |= TEA575X_MOST;
+
+	return ret;
+}
+
+static void bttv_tea575x_set_direction(struct snd_tea575x *tea, bool output)
 {
-	int freq;
+	struct bttv *btv = tea->private_data;
+	struct bttv_tea575x_gpio gpio = btv->tea_gpio;
+	u32 mask = (1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) |
+		   (1 << gpio.most);
+
+	if (output)
+		gpio_inout(mask, (1 << gpio.data) | (1 << gpio.clk) |
+				 (1 << gpio.wren));
+	else
+		gpio_inout(mask, (1 << gpio.clk) | (1 << gpio.wren));
+}
+
+static struct snd_tea575x_ops bttv_tea_ops = {
+	.set_pins = bttv_tea575x_set_pins,
+	.get_pins = bttv_tea575x_get_pins,
+	.set_direction = bttv_tea575x_set_direction,
+};
+
+static int tea575x_init(struct bttv *btv)
+{
+	btv->tea.private_data = btv;
+	btv->tea.ops = &bttv_tea_ops;
+	if (!snd_tea575x_hw_init(&btv->tea)) {
+		pr_info("%d: detected TEA575x radio\n", btv->c.nr);
+		btv->tea.mute = false;
+		return 0;
+	}
+
+	btv->has_tea575x = 0;
+	btv->has_radio = 0;
 
+	return -ENODEV;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int terratec_active_radio_upgrade(struct bttv *btv)
+{
 	btv->has_radio    = 1;
-	btv->has_matchbox = 1;
-	btv->mbox_we      = 0x10;
-	btv->mbox_most    = 0x20;
-	btv->mbox_clk     = 0x08;
-	btv->mbox_data    = 0x04;
-	btv->mbox_mask    = 0x3c;
+	btv->has_tea575x  = 1;
+	btv->tea_gpio.wren = 4;
+	btv->tea_gpio.most = 5;
+	btv->tea_gpio.clk  = 3;
+	btv->tea_gpio.data = 2;
 
 	btv->mbox_iow     = 1 <<  8;
 	btv->mbox_ior     = 1 <<  9;
 	btv->mbox_csel    = 1 << 10;
 
-	freq=88000/62.5;
-	tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
-	if (0x1ed8 == tea5757_read(btv)) {
+	if (!tea575x_init(btv)) {
 		pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
-		btv->has_radio    = 1;
-		btv->has_saa6588  = 1;
-		btv->has_matchbox = 1;
-	} else {
-		btv->has_radio    = 0;
-		btv->has_matchbox = 0;
+		btv->has_saa6588 = 1;
 	}
+
 	return 0;
 }
 
@@ -4292,181 +4370,6 @@ init_PCI8604PW(struct bttv *btv)
 	}
 }
 
-
-
-/* ----------------------------------------------------------------------- */
-/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports     */
-/*
- * Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
- * This code is placed under the terms of the GNU General Public License
- *
- * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
- */
-
-static void bus_low(struct bttv *btv, int bit)
-{
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-		udelay(5);
-	}
-
-	gpio_bits(bit,0);
-	udelay(5);
-
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
-		udelay(5);
-	}
-}
-
-static void bus_high(struct bttv *btv, int bit)
-{
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-		udelay(5);
-	}
-
-	gpio_bits(bit,bit);
-	udelay(5);
-
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
-		udelay(5);
-	}
-}
-
-static int bus_in(struct bttv *btv, int bit)
-{
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-		udelay(5);
-
-		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
-		udelay(5);
-	}
-	return gpio_read() & (bit);
-}
-
-/* TEA5757 register bits */
-#define TEA_FREQ		0:14
-#define TEA_BUFFER		15:15
-
-#define TEA_SIGNAL_STRENGTH	16:17
-
-#define TEA_PORT1		18:18
-#define TEA_PORT0		19:19
-
-#define TEA_BAND		20:21
-#define TEA_BAND_FM		0
-#define TEA_BAND_MW		1
-#define TEA_BAND_LW		2
-#define TEA_BAND_SW		3
-
-#define TEA_MONO		22:22
-#define TEA_ALLOW_STEREO	0
-#define TEA_FORCE_MONO		1
-
-#define TEA_SEARCH_DIRECTION	23:23
-#define TEA_SEARCH_DOWN		0
-#define TEA_SEARCH_UP		1
-
-#define TEA_STATUS		24:24
-#define TEA_STATUS_TUNED	0
-#define TEA_STATUS_SEARCHING	1
-
-/* Low-level stuff */
-static int tea5757_read(struct bttv *btv)
-{
-	unsigned long timeout;
-	int value = 0;
-	int i;
-
-	/* better safe than sorry */
-	gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
-
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-		udelay(5);
-	}
-
-	if (bttv_gpio)
-		bttv_gpio_tracking(btv,"tea5757 read");
-
-	bus_low(btv,btv->mbox_we);
-	bus_low(btv,btv->mbox_clk);
-
-	udelay(10);
-	timeout= jiffies + msecs_to_jiffies(1000);
-
-	/* wait for DATA line to go low; error if it doesn't */
-	while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
-		schedule();
-	if (bus_in(btv,btv->mbox_data)) {
-		pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
-		return -1;
-	}
-
-	dprintk("%d: tea5757:", btv->c.nr);
-	for (i = 0; i < 24; i++) {
-		udelay(5);
-		bus_high(btv,btv->mbox_clk);
-		udelay(5);
-		dprintk_cont("%c",
-			     bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
-		bus_low(btv,btv->mbox_clk);
-		value <<= 1;
-		value |= (bus_in(btv,btv->mbox_data) == 0)?0:1;  /* MSB first */
-		dprintk_cont("%c",
-			     bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
-	}
-	dprintk_cont("\n");
-	dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
-	return value;
-}
-
-static int tea5757_write(struct bttv *btv, int value)
-{
-	int i;
-	int reg = value;
-
-	gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
-
-	if (btv->mbox_ior) {
-		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-		udelay(5);
-	}
-	if (bttv_gpio)
-		bttv_gpio_tracking(btv,"tea5757 write");
-
-	dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
-	bus_low(btv,btv->mbox_clk);
-	bus_high(btv,btv->mbox_we);
-	for (i = 0; i < 25; i++) {
-		if (reg & 0x1000000)
-			bus_high(btv,btv->mbox_data);
-		else
-			bus_low(btv,btv->mbox_data);
-		reg <<= 1;
-		bus_high(btv,btv->mbox_clk);
-		udelay(10);
-		bus_low(btv,btv->mbox_clk);
-		udelay(10);
-	}
-	bus_low(btv,btv->mbox_we);  /* unmute !!! */
-	return 0;
-}
-
-void tea5757_set_freq(struct bttv *btv, unsigned short freq)
-{
-	dprintk("tea5757_set_freq %d\n",freq);
-	tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
-}
-
 /* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
  *
  * This is needed because rv605 don't use a normal multiplex, but a crosspoint
@@ -5048,10 +4951,3 @@ int bttv_handle_chipset(struct bttv *btv)
 		pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency);
 	return 0;
 }
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 4a8176c09fc9..4ec2a3c3f23c 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1874,8 +1874,10 @@ static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f)
 	if (new_freq.type == V4L2_TUNER_RADIO) {
 		radio_enable(btv);
 		btv->radio_freq = new_freq.frequency;
-		if (btv->has_matchbox)
-			tea5757_set_freq(btv, btv->radio_freq);
+		if (btv->has_tea575x) {
+			btv->tea.freq = btv->radio_freq;
+			snd_tea575x_set_freq(&btv->tea);
+		}
 	} else {
 		btv->tv_freq = new_freq.frequency;
 	}
@@ -2513,6 +2515,8 @@ static int bttv_querycap(struct file *file, void  *priv,
 		if (btv->has_saa6588)
 			cap->device_caps |= V4L2_CAP_READWRITE |
 						V4L2_CAP_RDS_CAPTURE;
+		if (btv->has_tea575x)
+			cap->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
 	}
 	return 0;
 }
@@ -3242,6 +3246,9 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	if (btv->audio_mode_gpio)
 		btv->audio_mode_gpio(btv, t, 0);
 
+	if (btv->has_tea575x)
+		return snd_tea575x_g_tuner(&btv->tea, t);
+
 	return 0;
 }
 
@@ -3259,6 +3266,30 @@ static int radio_s_tuner(struct file *file, void *priv,
 	return 0;
 }
 
+static int radio_s_hw_freq_seek(struct file *file, void *priv,
+					const struct v4l2_hw_freq_seek *a)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (btv->has_tea575x)
+		return snd_tea575x_s_hw_freq_seek(file, &btv->tea, a);
+
+	return -ENOTTY;
+}
+
+static int radio_enum_freq_bands(struct file *file, void *priv,
+					 struct v4l2_frequency_band *band)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (btv->has_tea575x)
+		return snd_tea575x_enum_freq_bands(&btv->tea, band);
+
+	return -ENOTTY;
+}
+
 static ssize_t radio_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
@@ -3316,6 +3347,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_s_tuner         = radio_s_tuner,
 	.vidioc_g_frequency     = bttv_g_frequency,
 	.vidioc_s_frequency     = bttv_s_frequency,
+	.vidioc_s_hw_freq_seek	= radio_s_hw_freq_seek,
+	.vidioc_enum_freq_bands	= radio_enum_freq_bands,
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
@@ -3884,7 +3917,6 @@ static struct video_device *vdev_init(struct bttv *btv,
 	*vfd = *template;
 	vfd->v4l2_dev = &btv->c.v4l2_dev;
 	vfd->release = video_device_release;
-	vfd->debug   = bttv_debug;
 	video_set_drvdata(vfd, btv);
 	snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
 		 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
@@ -4429,9 +4461,3 @@ static void __exit bttv_cleanup_module(void)
 
 module_init(bttv_init_module);
 module_exit(bttv_cleanup_module);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c
index 3f364b7062b9..25b9916906d5 100644
--- a/drivers/media/pci/bt8xx/bttv-gpio.c
+++ b/drivers/media/pci/bt8xx/bttv-gpio.c
@@ -181,9 +181,3 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
 	btwrite(data,BT848_GPIO_DATA);
 	spin_unlock_irqrestore(&btv->gpio_lock,flags);
 }
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttv-if.c b/drivers/media/pci/bt8xx/bttv-if.c
index a6a540dc9e4b..538652e16a5c 100644
--- a/drivers/media/pci/bt8xx/bttv-if.c
+++ b/drivers/media/pci/bt8xx/bttv-if.c
@@ -113,9 +113,3 @@ int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
 		bttv_gpio_tracking(btv,"extern write");
 	return 0;
 }
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c
index 4d3f05a19af3..3859dde98be2 100644
--- a/drivers/media/pci/bt8xx/bttv-risc.c
+++ b/drivers/media/pci/bt8xx/bttv-risc.c
@@ -901,9 +901,3 @@ bttv_overlay_risc(struct bttv *btv,
 	buf->vb.field = ov->field;
 	return 0;
 }
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c
index b433267d9aa9..e77129c92fa0 100644
--- a/drivers/media/pci/bt8xx/bttv-vbi.c
+++ b/drivers/media/pci/bt8xx/bttv-vbi.c
@@ -450,10 +450,3 @@ void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
 	/* See bttv_vbi_fmt_set(). */
 	f->end                  = tvnorm->vbistart[0] * 2 + 2;
 }
-
-/* ----------------------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h
index f08126244662..91301c3cad1e 100644
--- a/drivers/media/pci/bt8xx/bttv.h
+++ b/drivers/media/pci/bt8xx/bttv.h
@@ -378,8 +378,3 @@ extern void bttv_input_fini(struct bttv *dev);
 extern void bttv_input_irq(struct bttv *dev);
 
 #endif /* _BTTV_H_ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 9fe19488b30b..bc048c586b1f 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -42,6 +42,7 @@
 #include <media/tveeprom.h>
 #include <media/rc-core.h>
 #include <media/ir-kbd-i2c.h>
+#include <media/tea575x.h>
 
 #include "bt848.h"
 #include "bttv.h"
@@ -359,6 +360,10 @@ struct bttv_suspend_state {
 	struct bttv_buffer     *vbi;
 };
 
+struct bttv_tea575x_gpio {
+	u8 data, clk, wren, most;
+};
+
 struct bttv {
 	struct bttv_core c;
 
@@ -445,12 +450,9 @@ struct bttv {
 
 	/* miro/pinnacle + Aimslab VHX
 	   philips matchbox (tea5757 radio tuner) support */
-	int has_matchbox;
-	int mbox_we;
-	int mbox_data;
-	int mbox_clk;
-	int mbox_most;
-	int mbox_mask;
+	int has_tea575x;
+	struct bttv_tea575x_gpio tea_gpio;
+	struct snd_tea575x tea;
 
 	/* ISA stuff (Terratec Active Radio Upgrade) */
 	int mbox_ior;
@@ -531,9 +533,3 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv,
 #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
 
 #endif /* _BTTVP_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
index f613314b360b..74d774e5227b 100644
--- a/drivers/media/pci/cx23885/Kconfig
+++ b/drivers/media/pci/cx23885/Kconfig
@@ -41,6 +41,7 @@ config VIDEO_CX23885
 	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  This is a video4linux driver for Conexant 23885 based
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 06931f6fa26c..f384f295676e 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -710,6 +710,11 @@ struct cx23885_board cx23885_boards[] = {
 		.portb		= CX23885_MPEG_DVB,
 		.portc		= CX23885_MPEG_DVB,
 	},
+	[CX23885_BOARD_HAUPPAUGE_HVR5525] = {
+		.name		= "Hauppauge WinTV-HVR5525",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -993,6 +998,10 @@ struct cx23885_subid cx23885_subids[] = {
 		.subvendor = 0x4254,
 		.subdevice = 0x0982,
 		.card      = CX23885_BOARD_DVBSKY_T982,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0xf038,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR5525,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1165,6 +1174,8 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
 	case 85721:
 		/* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
 			Dual channel ATSC and Basic analog */
+	case 150329:
+		/* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */
 		break;
 	default:
 		printk(KERN_WARNING "%s: warning: "
@@ -1637,6 +1648,29 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
 		msleep(100);
 		cx23885_gpio_set(dev, GPIO_2);
 		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR5525:
+		/*
+		 * GPIO-00 IR_WIDE
+		 * GPIO-02 wake#
+		 * GPIO-03 VAUX Pres.
+		 * GPIO-07 PROG#
+		 * GPIO-08 SAT_RESN
+		 * GPIO-09 TER_RESN
+		 * GPIO-10 B2_SENSE
+		 * GPIO-11 B1_SENSE
+		 * GPIO-15 IR_LED_STATUS
+		 * GPIO-19 IR_NARROW
+		 * GPIO-20 Blauster1
+		 * ALTGPIO VAUX_SWITCH
+		 * AUX_PLL_CLK : Blaster2
+		 */
+		/* Put the parts into reset and back */
+		cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
+		cx23885_gpio_clear(dev, GPIO_8 | GPIO_9);
+		msleep(100);
+		cx23885_gpio_set(dev, GPIO_8 | GPIO_9);
+		msleep(100);
+		break;
 	}
 }
 
@@ -1879,6 +1913,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
 	case CX23885_BOARD_HAUPPAUGE_HVR4400:
 	case CX23885_BOARD_HAUPPAUGE_STARBURST:
 	case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
+	case CX23885_BOARD_HAUPPAUGE_HVR5525:
 		if (dev->i2c_bus[0].i2c_rc == 0)
 			hauppauge_eeprom(dev, eeprom+0xc0);
 		break;
@@ -2008,6 +2043,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR5525:
+		ts1->gen_ctrl_val  = 0x5; /* Parallel */
+		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index a9c450d4b54e..45fbe1e4d2d0 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -74,6 +74,7 @@
 #include "sp2.h"
 #include "m88ds3103.h"
 #include "m88ts2022.h"
+#include "m88rs6000t.h"
 
 static unsigned int debug;
 
@@ -915,6 +916,16 @@ static const struct m88ds3103_config dvbsky_s952_portc_m88ds3103_config = {
 	.agc = 0x99,
 };
 
+static const struct m88ds3103_config hauppauge_hvr5525_m88ds3103_config = {
+	.i2c_addr = 0x69,
+	.clock = 27000000,
+	.i2c_wr_max = 33,
+	.ts_mode = M88DS3103_TS_PARALLEL,
+	.ts_clk = 16000,
+	.ts_clk_pol = 1,
+	.agc = 0x99,
+};
+
 static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
 	struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -1058,6 +1069,116 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
 	.hostbus_diversity = 1,
 };
 
+static int dvb_register_ci_mac(struct cx23885_tsport *port)
+{
+	struct cx23885_dev *dev = port->dev;
+	struct i2c_client *client_ci = NULL;
+	struct vb2_dvb_frontend *fe0;
+
+	fe0 = vb2_dvb_get_frontend(&port->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
+	switch (dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
+		static struct netup_card_info cinfo;
+
+		netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+		memcpy(port->frontends.adapter.proposed_mac,
+				cinfo.port[port->nr - 1].mac, 6);
+		printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
+			port->nr, port->frontends.adapter.proposed_mac);
+
+		netup_ci_init(port);
+		return 0;
+		}
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+		struct altera_ci_config netup_ci_cfg = {
+			.dev = dev,/* magic number to identify*/
+			.adapter = &port->frontends.adapter,/* for CI */
+			.demux = &fe0->dvb.demux,/* for hw pid filter */
+			.fpga_rw = netup_altera_fpga_rw,
+		};
+
+		altera_ci_init(&netup_ci_cfg, port->nr);
+		return 0;
+		}
+	case CX23885_BOARD_TEVII_S470: {
+		u8 eeprom[256]; /* 24C02 i2c eeprom */
+
+		if (port->nr != 1)
+			return 0;
+
+		/* Read entire EEPROM */
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
+		printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
+		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
+		return 0;
+		}
+	case CX23885_BOARD_DVBSKY_T9580:
+	case CX23885_BOARD_DVBSKY_S950:
+	case CX23885_BOARD_DVBSKY_S952:
+	case CX23885_BOARD_DVBSKY_T982: {
+		u8 eeprom[256]; /* 24C02 i2c eeprom */
+
+		if (port->nr > 2)
+			return 0;
+
+		/* Read entire EEPROM */
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+				sizeof(eeprom));
+		printk(KERN_INFO "%s port %d MAC address: %pM\n",
+			cx23885_boards[dev->board].name, port->nr,
+			eeprom + 0xc0 + (port->nr-1) * 8);
+		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
+			(port->nr-1) * 8, 6);
+		return 0;
+		}
+	case CX23885_BOARD_DVBSKY_S950C:
+	case CX23885_BOARD_DVBSKY_T980C:
+	case CX23885_BOARD_TT_CT2_4500_CI: {
+		u8 eeprom[256]; /* 24C02 i2c eeprom */
+		struct sp2_config sp2_config;
+		struct i2c_board_info info;
+		struct cx23885_i2c *i2c_bus2 = &dev->i2c_bus[1];
+
+		/* attach CI */
+		memset(&sp2_config, 0, sizeof(sp2_config));
+		sp2_config.dvb_adap = &port->frontends.adapter;
+		sp2_config.priv = port;
+		sp2_config.ci_control = cx23885_sp2_ci_ctrl;
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "sp2", I2C_NAME_SIZE);
+		info.addr = 0x40;
+		info.platform_data = &sp2_config;
+		request_module(info.type);
+		client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
+		if (client_ci == NULL || client_ci->dev.driver == NULL)
+			return -ENODEV;
+		if (!try_module_get(client_ci->dev.driver->owner)) {
+			i2c_unregister_device(client_ci);
+			return -ENODEV;
+		}
+		port->i2c_client_ci = client_ci;
+
+		if (port->nr != 1)
+			return 0;
+
+		/* Read entire EEPROM */
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+				sizeof(eeprom));
+		printk(KERN_INFO "%s MAC address: %pM\n",
+			cx23885_boards[dev->board].name, eeprom + 0xc0);
+		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
+		return 0;
+		}
+	}
+	return 0;
+}
+
 static int dvb_register(struct cx23885_tsport *port)
 {
 	struct dib7000p_ops dib7000p_ops;
@@ -1066,11 +1187,10 @@ static int dvb_register(struct cx23885_tsport *port)
 	struct vb2_dvb_frontend *fe0, *fe1 = NULL;
 	struct si2168_config si2168_config;
 	struct si2157_config si2157_config;
-	struct sp2_config sp2_config;
 	struct m88ts2022_config m88ts2022_config;
 	struct i2c_board_info info;
 	struct i2c_adapter *adapter;
-	struct i2c_client *client_demod = NULL, *client_tuner = NULL, *client_ci = NULL;
+	struct i2c_client *client_demod = NULL, *client_tuner = NULL;
 	const struct m88ds3103_config *p_m88ds3103_config = NULL;
 	int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
 	int mfe_shared = 0; /* bus not shared by default */
@@ -1801,15 +1921,11 @@ static int dvb_register(struct cx23885_tsport *port)
 			request_module(info.type);
 			client_tuner = i2c_new_device(adapter, &info);
 			if (client_tuner == NULL ||
-					client_tuner->dev.driver == NULL) {
-				module_put(client_demod->dev.driver->owner);
-				i2c_unregister_device(client_demod);
+					client_tuner->dev.driver == NULL)
 				goto frontend_detach;
-			}
+
 			if (!try_module_get(client_tuner->dev.driver->owner)) {
 				i2c_unregister_device(client_tuner);
-				module_put(client_demod->dev.driver->owner);
-				i2c_unregister_device(client_demod);
 				goto frontend_detach;
 			}
 			port->i2c_client_tuner = client_tuner;
@@ -1832,8 +1948,7 @@ static int dvb_register(struct cx23885_tsport *port)
 		info.platform_data = &si2168_config;
 		request_module(info.type);
 		client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
-		if (client_demod == NULL ||
-				client_demod->dev.driver == NULL)
+		if (client_demod == NULL || client_demod->dev.driver == NULL)
 			goto frontend_detach;
 		if (!try_module_get(client_demod->dev.driver->owner)) {
 			i2c_unregister_device(client_demod);
@@ -1851,15 +1966,10 @@ static int dvb_register(struct cx23885_tsport *port)
 		request_module(info.type);
 		client_tuner = i2c_new_device(adapter, &info);
 		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL) {
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
+				client_tuner->dev.driver == NULL)
 			goto frontend_detach;
-		}
 		if (!try_module_get(client_tuner->dev.driver->owner)) {
 			i2c_unregister_device(client_tuner);
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
 			goto frontend_detach;
 		}
 		port->i2c_client_tuner = client_tuner;
@@ -1885,8 +1995,7 @@ static int dvb_register(struct cx23885_tsport *port)
 		info.platform_data = &m88ts2022_config;
 		request_module(info.type);
 		client_tuner = i2c_new_device(adapter, &info);
-		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL)
+		if (client_tuner == NULL || client_tuner->dev.driver == NULL)
 			goto frontend_detach;
 		if (!try_module_get(client_tuner->dev.driver->owner)) {
 			i2c_unregister_device(client_tuner);
@@ -1932,8 +2041,7 @@ static int dvb_register(struct cx23885_tsport *port)
 		info.platform_data = &m88ts2022_config;
 		request_module(info.type);
 		client_tuner = i2c_new_device(adapter, &info);
-		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL)
+		if (client_tuner == NULL || client_tuner->dev.driver == NULL)
 			goto frontend_detach;
 		if (!try_module_get(client_tuner->dev.driver->owner)) {
 			i2c_unregister_device(client_tuner);
@@ -1978,8 +2086,7 @@ static int dvb_register(struct cx23885_tsport *port)
 		info.platform_data = &si2168_config;
 		request_module(info.type);
 		client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
-		if (client_demod == NULL ||
-				client_demod->dev.driver == NULL)
+		if (client_demod == NULL || client_demod->dev.driver == NULL)
 			goto frontend_detach;
 		if (!try_module_get(client_demod->dev.driver->owner)) {
 			i2c_unregister_device(client_demod);
@@ -1997,20 +2104,101 @@ static int dvb_register(struct cx23885_tsport *port)
 		request_module(info.type);
 		client_tuner = i2c_new_device(adapter, &info);
 		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL) {
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
+				client_tuner->dev.driver == NULL)
 			goto frontend_detach;
-		}
 		if (!try_module_get(client_tuner->dev.driver->owner)) {
 			i2c_unregister_device(client_tuner);
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
-			port->i2c_client_demod = NULL;
 			goto frontend_detach;
 		}
 		port->i2c_client_tuner = client_tuner;
 		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR5525:
+		switch (port->nr) {
+		struct m88rs6000t_config m88rs6000t_config;
+
+		/* port b - satellite */
+		case 1:
+			/* attach frontend */
+			fe0->dvb.frontend = dvb_attach(m88ds3103_attach,
+					&hauppauge_hvr5525_m88ds3103_config,
+					&dev->i2c_bus[0].i2c_adap, &adapter);
+			if (fe0->dvb.frontend == NULL)
+				break;
+
+			/* attach SEC */
+			if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
+					&dev->i2c_bus[0].i2c_adap,
+					&hauppauge_a8293_config))
+				goto frontend_detach;
+
+			/* attach tuner */
+			memset(&m88rs6000t_config, 0, sizeof(m88rs6000t_config));
+			m88rs6000t_config.fe = fe0->dvb.frontend;
+			memset(&info, 0, sizeof(struct i2c_board_info));
+			strlcpy(info.type, "m88rs6000t", I2C_NAME_SIZE);
+			info.addr = 0x21;
+			info.platform_data = &m88rs6000t_config;
+			request_module("%s", info.type);
+			client_tuner = i2c_new_device(adapter, &info);
+			if (!client_tuner || !client_tuner->dev.driver)
+				goto frontend_detach;
+			if (!try_module_get(client_tuner->dev.driver->owner)) {
+				i2c_unregister_device(client_tuner);
+				goto frontend_detach;
+			}
+			port->i2c_client_tuner = client_tuner;
+
+			/* delegate signal strength measurement to tuner */
+			fe0->dvb.frontend->ops.read_signal_strength =
+				fe0->dvb.frontend->ops.tuner_ops.get_rf_strength;
+			break;
+		/* port c - terrestrial/cable */
+		case 2:
+			/* attach frontend */
+			memset(&si2168_config, 0, sizeof(si2168_config));
+			si2168_config.i2c_adapter = &adapter;
+			si2168_config.fe = &fe0->dvb.frontend;
+			si2168_config.ts_mode = SI2168_TS_SERIAL;
+			memset(&info, 0, sizeof(struct i2c_board_info));
+			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+			info.addr = 0x64;
+			info.platform_data = &si2168_config;
+			request_module("%s", info.type);
+			client_demod = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info);
+			if (!client_demod || !client_demod->dev.driver)
+				goto frontend_detach;
+			if (!try_module_get(client_demod->dev.driver->owner)) {
+				i2c_unregister_device(client_demod);
+				goto frontend_detach;
+			}
+			port->i2c_client_demod = client_demod;
+
+			/* attach tuner */
+			memset(&si2157_config, 0, sizeof(si2157_config));
+			si2157_config.fe = fe0->dvb.frontend;
+			memset(&info, 0, sizeof(struct i2c_board_info));
+			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+			info.addr = 0x60;
+			info.platform_data = &si2157_config;
+			request_module("%s", info.type);
+			client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info);
+			if (!client_tuner || !client_tuner->dev.driver) {
+				module_put(client_demod->dev.driver->owner);
+				i2c_unregister_device(client_demod);
+				port->i2c_client_demod = NULL;
+				goto frontend_detach;
+			}
+			if (!try_module_get(client_tuner->dev.driver->owner)) {
+				i2c_unregister_device(client_tuner);
+				module_put(client_demod->dev.driver->owner);
+				i2c_unregister_device(client_demod);
+				port->i2c_client_demod = NULL;
+				goto frontend_detach;
+			}
+			port->i2c_client_tuner = client_tuner;
+			break;
+		}
+		break;
 	default:
 		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
 			" isn't supported yet\n",
@@ -2047,123 +2235,29 @@ static int dvb_register(struct cx23885_tsport *port)
 	if (ret)
 		goto frontend_detach;
 
-	/* init CI & MAC */
-	switch (dev->board) {
-	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
-		static struct netup_card_info cinfo;
-
-		netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
-		memcpy(port->frontends.adapter.proposed_mac,
-				cinfo.port[port->nr - 1].mac, 6);
-		printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
-			port->nr, port->frontends.adapter.proposed_mac);
-
-		netup_ci_init(port);
-		break;
-		}
-	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
-		struct altera_ci_config netup_ci_cfg = {
-			.dev = dev,/* magic number to identify*/
-			.adapter = &port->frontends.adapter,/* for CI */
-			.demux = &fe0->dvb.demux,/* for hw pid filter */
-			.fpga_rw = netup_altera_fpga_rw,
-		};
-
-		altera_ci_init(&netup_ci_cfg, port->nr);
-		break;
-		}
-	case CX23885_BOARD_TEVII_S470: {
-		u8 eeprom[256]; /* 24C02 i2c eeprom */
-
-		if (port->nr != 1)
-			break;
-
-		/* Read entire EEPROM */
-		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
-		printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
-		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
-		break;
-		}
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982: {
-		u8 eeprom[256]; /* 24C02 i2c eeprom */
-
-		if (port->nr > 2)
-			break;
-
-		/* Read entire EEPROM */
-		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
-				sizeof(eeprom));
-		printk(KERN_INFO "%s port %d MAC address: %pM\n",
-			cx23885_boards[dev->board].name, port->nr,
-			eeprom + 0xc0 + (port->nr-1) * 8);
-		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
-			(port->nr-1) * 8, 6);
-		break;
-		}
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_TT_CT2_4500_CI: {
-		u8 eeprom[256]; /* 24C02 i2c eeprom */
-
-		/* attach CI */
-		memset(&sp2_config, 0, sizeof(sp2_config));
-		sp2_config.dvb_adap = &port->frontends.adapter;
-		sp2_config.priv = port;
-		sp2_config.ci_control = cx23885_sp2_ci_ctrl;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "sp2", I2C_NAME_SIZE);
-		info.addr = 0x40;
-		info.platform_data = &sp2_config;
-		request_module(info.type);
-		client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
-		if (client_ci == NULL ||
-				client_ci->dev.driver == NULL) {
-			if (client_tuner) {
-				module_put(client_tuner->dev.driver->owner);
-				i2c_unregister_device(client_tuner);
-			}
-			if (client_demod) {
-				module_put(client_demod->dev.driver->owner);
-				i2c_unregister_device(client_demod);
-			}
-			goto frontend_detach;
-		}
-		if (!try_module_get(client_ci->dev.driver->owner)) {
-			i2c_unregister_device(client_ci);
-			if (client_tuner) {
-				module_put(client_tuner->dev.driver->owner);
-				i2c_unregister_device(client_tuner);
-			}
-			if (client_demod) {
-				module_put(client_demod->dev.driver->owner);
-				i2c_unregister_device(client_demod);
-			}
-			goto frontend_detach;
-		}
-		port->i2c_client_ci = client_ci;
+	ret = dvb_register_ci_mac(port);
+	if (ret)
+		goto frontend_detach;
 
-		if (port->nr != 1)
-			break;
+	return 0;
 
-		/* Read entire EEPROM */
-		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
-				sizeof(eeprom));
-		printk(KERN_INFO "%s MAC address: %pM\n",
-			cx23885_boards[dev->board].name, eeprom + 0xc0);
-		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
-		break;
-		}
+frontend_detach:
+	/* remove I2C client for tuner */
+	client_tuner = port->i2c_client_tuner;
+	if (client_tuner) {
+		module_put(client_tuner->dev.driver->owner);
+		i2c_unregister_device(client_tuner);
+		port->i2c_client_tuner = NULL;
 	}
 
-	return ret;
+	/* remove I2C client for demodulator */
+	client_demod = port->i2c_client_demod;
+	if (client_demod) {
+		module_put(client_demod->dev.driver->owner);
+		i2c_unregister_device(client_demod);
+		port->i2c_client_demod = NULL;
+	}
 
-frontend_detach:
 	port->gate_ctrl = NULL;
 	vb2_dvb_dealloc_frontends(&port->frontends);
 	return -EINVAL;
diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c
index fd71306af6e2..1135ea3f6ce5 100644
--- a/drivers/media/pci/cx23885/cx23885-i2c.c
+++ b/drivers/media/pci/cx23885/cx23885-i2c.c
@@ -300,8 +300,8 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
 		rc = i2c_master_recv(c, &buf, 0);
 		if (rc < 0)
 			continue;
-		printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
-		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+		printk(KERN_INFO "%s: i2c scan: found device @ 0x%04x  [%s]\n",
+		       name, i, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 }
 
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 36f2f96c40e4..aeda8d3990ae 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -99,7 +99,8 @@
 #define CX23885_BOARD_DVBSKY_S950              49
 #define CX23885_BOARD_DVBSKY_S952              50
 #define CX23885_BOARD_DVBSKY_T982              51
-#define CX23885_BOARD_HAUPPAUGE_STARBURST      52
+#define CX23885_BOARD_HAUPPAUGE_HVR5525        52
+#define CX23885_BOARD_HAUPPAUGE_STARBURST      53
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig
index 6439a847680c..1755d3d2feaa 100644
--- a/drivers/media/pci/cx25821/Kconfig
+++ b/drivers/media/pci/cx25821/Kconfig
@@ -2,8 +2,7 @@ config VIDEO_CX25821
 	tristate "Conexant cx25821 support"
 	depends on VIDEO_DEV && PCI && I2C
 	select I2C_ALGOBIT
-	select VIDEO_BTCX
-	select VIDEOBUF_DMA_SG
+	select VIDEOBUF2_DMA_SG
 	---help---
 	  This is a video4linux driver for Conexant 25821 based
 	  TV cards.
diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile
index fb76c3d3713a..c8f8598a2b86 100644
--- a/drivers/media/pci/cx25821/Makefile
+++ b/drivers/media/pci/cx25821/Makefile
@@ -1,9 +1,8 @@
 cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
 		       cx25821-gpio.o cx25821-medusa-video.o \
-		       cx25821-video.o cx25821-video-upstream.o
+		       cx25821-video.o
 
 obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
 obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
 
 ccflags-y += -Idrivers/media/i2c
-ccflags-y += -Idrivers/media/common
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index 2dd5bcaa7e53..24f964bcc53a 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -63,8 +63,11 @@ static int devno;
 
 struct cx25821_audio_buffer {
 	unsigned int bpl;
-	struct btcx_riscmem risc;
-	struct videobuf_dmabuf dma;
+	struct cx25821_riscmem risc;
+	void			*vaddr;
+	struct scatterlist	*sglist;
+	int                     sglen;
+	int                     nr_pages;
 };
 
 struct cx25821_audio_dev {
@@ -87,8 +90,6 @@ struct cx25821_audio_dev {
 	unsigned int period_size;
 	unsigned int num_periods;
 
-	struct videobuf_dmabuf *dma_risc;
-
 	struct cx25821_audio_buffer *buf;
 
 	struct snd_pcm_substream *substream;
@@ -142,6 +143,83 @@ MODULE_PARM_DESC(debug, "enable debug messages");
 
 #define PCI_MSK_AUD_EXT   (1 <<  4)
 #define PCI_MSK_AUD_INT   (1 <<  3)
+
+static int cx25821_alsa_dma_init(struct cx25821_audio_dev *chip, int nr_pages)
+{
+	struct cx25821_audio_buffer *buf = chip->buf;
+	struct page *pg;
+	int i;
+
+	buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+	if (NULL == buf->vaddr) {
+		dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
+		return -ENOMEM;
+	}
+
+	dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
+				(unsigned long)buf->vaddr,
+				nr_pages << PAGE_SHIFT);
+
+	memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
+	buf->nr_pages = nr_pages;
+
+	buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
+	if (NULL == buf->sglist)
+		goto vzalloc_err;
+
+	sg_init_table(buf->sglist, buf->nr_pages);
+	for (i = 0; i < buf->nr_pages; i++) {
+		pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
+		if (NULL == pg)
+			goto vmalloc_to_page_err;
+		sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
+	}
+	return 0;
+
+vmalloc_to_page_err:
+	vfree(buf->sglist);
+	buf->sglist = NULL;
+vzalloc_err:
+	vfree(buf->vaddr);
+	buf->vaddr = NULL;
+	return -ENOMEM;
+}
+
+static int cx25821_alsa_dma_map(struct cx25821_audio_dev *dev)
+{
+	struct cx25821_audio_buffer *buf = dev->buf;
+
+	buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
+			buf->nr_pages, PCI_DMA_FROMDEVICE);
+
+	if (0 == buf->sglen) {
+		pr_warn("%s: cx25821_alsa_map_sg failed\n", __func__);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int cx25821_alsa_dma_unmap(struct cx25821_audio_dev *dev)
+{
+	struct cx25821_audio_buffer *buf = dev->buf;
+
+	if (!buf->sglen)
+		return 0;
+
+	dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE);
+	buf->sglen = 0;
+	return 0;
+}
+
+static int cx25821_alsa_dma_free(struct cx25821_audio_buffer *buf)
+{
+	vfree(buf->sglist);
+	buf->sglist = NULL;
+	vfree(buf->vaddr);
+	buf->vaddr = NULL;
+	return 0;
+}
+
 /*
  * BOARD Specific: Sets audio DMA
  */
@@ -330,15 +408,17 @@ out:
 
 static int dsp_buffer_free(struct cx25821_audio_dev *chip)
 {
+	struct cx25821_riscmem *risc = &chip->buf->risc;
+
 	BUG_ON(!chip->dma_size);
 
 	dprintk(2, "Freeing buffer\n");
-	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
-	videobuf_dma_free(chip->dma_risc);
-	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	cx25821_alsa_dma_unmap(chip);
+	cx25821_alsa_dma_free(chip->buf);
+	pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma);
 	kfree(chip->buf);
 
-	chip->dma_risc = NULL;
+	chip->buf = NULL;
 	chip->dma_size = 0;
 
 	return 0;
@@ -430,8 +510,6 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *hw_params)
 {
 	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
-	struct videobuf_dmabuf *dma;
-
 	struct cx25821_audio_buffer *buf;
 	int ret;
 
@@ -455,19 +533,18 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
 		chip->period_size = AUDIO_LINE_SIZE;
 
 	buf->bpl = chip->period_size;
+	chip->buf = buf;
 
-	dma = &buf->dma;
-	videobuf_dma_init(dma);
-	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+	ret = cx25821_alsa_dma_init(chip,
 			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
 	if (ret < 0)
 		goto error;
 
-	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	ret = cx25821_alsa_dma_map(chip);
 	if (ret < 0)
 		goto error;
 
-	ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+	ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, buf->sglist,
 			chip->period_size, chip->num_periods, 1);
 	if (ret < 0) {
 		pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
@@ -479,16 +556,14 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
 	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 	buf->risc.jmp[2] = cpu_to_le32(0);	/* bits 63-32 */
 
-	chip->buf = buf;
-	chip->dma_risc = dma;
-
-	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_area = chip->buf->vaddr;
 	substream->runtime->dma_bytes = chip->dma_size;
 	substream->runtime->dma_addr = 0;
 
 	return 0;
 
 error:
+	chip->buf = NULL;
 	kfree(buf);
 	return ret;
 }
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
index 389fffd2f36f..559f8293c53a 100644
--- a/drivers/media/pci/cx25821/cx25821-core.c
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -874,10 +874,9 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
 	if (dev->pci->device != 0x8210) {
 		pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
 			__func__, dev->pci->device);
-		return -1;
-	} else {
-		pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
+		return -ENODEV;
 	}
+	pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
 
 	/* Apply a sensible clock frequency for the PCIe bridge */
 	dev->clk_freq = 28000000;
@@ -966,11 +965,15 @@ void cx25821_dev_unregister(struct cx25821_dev *dev)
 
 	release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
 
-	for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; i++) {
+	for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; i++) {
 		if (i == SRAM_CH08) /* audio channel */
 			continue;
+		/*
+		 * TODO: enable when video output is properly
+		 * supported.
 		if (i == SRAM_CH09 || i == SRAM_CH10)
 			cx25821_free_mem_upstream(&dev->channels[i]);
+		 */
 		cx25821_video_unregister(dev, i);
 	}
 
@@ -979,14 +982,41 @@ void cx25821_dev_unregister(struct cx25821_dev *dev)
 }
 EXPORT_SYMBOL(cx25821_dev_unregister);
 
+int cx25821_riscmem_alloc(struct pci_dev *pci,
+		       struct cx25821_riscmem *risc,
+		       unsigned int size)
+{
+	__le32 *cpu;
+	dma_addr_t dma = 0;
+
+	if (NULL != risc->cpu && risc->size < size)
+		pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
+	if (NULL == risc->cpu) {
+		cpu = pci_zalloc_consistent(pci, size, &dma);
+		if (NULL == cpu)
+			return -ENOMEM;
+		risc->cpu  = cpu;
+		risc->dma  = dma;
+		risc->size = size;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_riscmem_alloc);
+
 static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
 				  unsigned int offset, u32 sync_line,
 				  unsigned int bpl, unsigned int padding,
-				  unsigned int lines)
+				  unsigned int lines, bool jump)
 {
 	struct scatterlist *sg;
 	unsigned int line, todo;
 
+	if (jump) {
+		*(rp++) = cpu_to_le32(RISC_JUMP);
+		*(rp++) = cpu_to_le32(0);
+		*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+	}
+
 	/* sync instruction */
 	if (sync_line != NO_SYNC_LINE)
 		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
@@ -1035,7 +1065,7 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
 	return rp;
 }
 
-int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc,
 			struct scatterlist *sglist, unsigned int top_offset,
 			unsigned int bottom_offset, unsigned int bpl,
 			unsigned int padding, unsigned int lines)
@@ -1052,14 +1082,14 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 		fields++;
 
 	/* estimate risc mem: worst case is one write per page border +
-	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   one write per scan line + syncs + jump (all 3 dwords).  Padding
 	   can cause next bpl to start close to a page border.  First DMA
 	   region may be smaller than PAGE_SIZE */
 	/* write and jump need and extra dword */
 	instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE +
 			lines);
-	instructions += 2;
-	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+	instructions += 5;
+	rc = cx25821_riscmem_alloc(pci, risc, instructions * 12);
 
 	if (rc < 0)
 		return rc;
@@ -1069,17 +1099,17 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 
 	if (UNSET != top_offset) {
 		rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
-					lines);
+					lines, true);
 	}
 
 	if (UNSET != bottom_offset) {
 		rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
-					padding, lines);
+					padding, lines, UNSET == top_offset);
 	}
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
-	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	BUG_ON((risc->jmp - risc->cpu + 3) * sizeof(*risc->cpu) > risc->size);
 
 	return 0;
 }
@@ -1146,7 +1176,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
 }
 
 int cx25821_risc_databuffer_audio(struct pci_dev *pci,
-				  struct btcx_riscmem *risc,
+				  struct cx25821_riscmem *risc,
 				  struct scatterlist *sglist,
 				  unsigned int bpl,
 				  unsigned int lines, unsigned int lpi)
@@ -1163,7 +1193,7 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci,
 	instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
 	instructions += 1;
 
-	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+	rc = cx25821_riscmem_alloc(pci, risc, instructions * 12);
 	if (rc < 0)
 		return rc;
 
@@ -1179,40 +1209,14 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci,
 }
 EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
 
-int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-			 u32 reg, u32 mask, u32 value)
-{
-	__le32 *rp;
-	int rc;
-
-	rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
-
-	if (rc < 0)
-		return rc;
-
-	/* write risc instructions */
-	rp = risc->cpu;
-
-	*(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
-	*(rp++) = cpu_to_le32(reg);
-	*(rp++) = cpu_to_le32(value);
-	*(rp++) = cpu_to_le32(mask);
-	*(rp++) = cpu_to_le32(RISC_JUMP);
-	*(rp++) = cpu_to_le32(risc->dma);
-	*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
-	return 0;
-}
-
-void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+void cx25821_free_buffer(struct cx25821_dev *dev, struct cx25821_buffer *buf)
 {
-	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-
 	BUG_ON(in_interrupt());
-	videobuf_waiton(q, &buf->vb, 0, 0);
-	videobuf_dma_unmap(q->dev, dma);
-	videobuf_dma_free(dma);
-	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+	if (WARN_ON(buf->risc.size == 0))
+		return;
+	pci_free_consistent(dev->pci,
+			buf->risc.size, buf->risc.cpu, buf->risc.dma);
+	memset(&buf->risc, 0, sizeof(buf->risc));
 }
 
 static irqreturn_t cx25821_irq(int irq, void *dev_id)
@@ -1297,14 +1301,15 @@ static int cx25821_initdev(struct pci_dev *pci_dev,
 
 		goto fail_unregister_device;
 	}
+	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
+	if (IS_ERR(dev->alloc_ctx)) {
+		err = PTR_ERR(dev->alloc_ctx);
+		goto fail_unregister_pci;
+	}
 
 	err = cx25821_dev_setup(dev);
-	if (err) {
-		if (err == -EBUSY)
-			goto fail_unregister_device;
-		else
-			goto fail_unregister_pci;
-	}
+	if (err)
+		goto fail_free_ctx;
 
 	/* print pci info */
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
@@ -1334,6 +1339,8 @@ fail_irq:
 	pr_info("cx25821_initdev() can't get IRQ !\n");
 	cx25821_dev_unregister(dev);
 
+fail_free_ctx:
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 fail_unregister_pci:
 	pci_disable_device(pci_dev);
 fail_unregister_device:
@@ -1357,6 +1364,7 @@ static void cx25821_finidev(struct pci_dev *pci_dev)
 		free_irq(pci_dev->irq, dev);
 
 	cx25821_dev_unregister(dev);
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	v4l2_device_unregister(v4l2_dev);
 	kfree(dev);
 }
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index 3a419f134584..7bc495e4ece2 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2009 Conexant Systems Inc.
  *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *  Based on Steven Toth <stoth@linuxtv.org> cx25821 driver
  *  Parts adapted/taken from Eduardo Moscoso Rubino
  *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com>
  *
@@ -46,10 +46,6 @@ static unsigned int irq_debug;
 module_param(irq_debug, int, 0644);
 MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
 
-static unsigned int vid_limit = 16;
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
-
 #define FORMAT_FLAGS_PACKED       0x01
 
 static const struct cx25821_fmt formats[] = {
@@ -76,41 +72,6 @@ static const struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
 	return NULL;
 }
 
-void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
-			  u32 count)
-{
-	struct cx25821_buffer *buf;
-	int bc;
-
-	for (bc = 0;; bc++) {
-		if (list_empty(&q->active)) {
-			dprintk(1, "bc=%d (=0: active empty)\n", bc);
-			break;
-		}
-
-		buf = list_entry(q->active.next, struct cx25821_buffer,
-				vb.queue);
-
-		/* count comes from the hw and it is 16bit wide --
-		 * this trick handles wrap-arounds correctly for
-		 * up to 32767 buffers in flight... */
-		if ((s16) (count - buf->count) < 0)
-			break;
-
-		v4l2_get_timestamp(&buf->vb.ts);
-		buf->vb.state = VIDEOBUF_DONE;
-		list_del(&buf->vb.queue);
-		wake_up(&buf->vb.done);
-	}
-
-	if (list_empty(&q->active))
-		del_timer(&q->timeout);
-	else
-		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-	if (bc != 1)
-		pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc);
-}
-
 int cx25821_start_video_dma(struct cx25821_dev *dev,
 			    struct cx25821_dmaqueue *q,
 			    struct cx25821_buffer *buf,
@@ -123,7 +84,6 @@ int cx25821_start_video_dma(struct cx25821_dev *dev,
 
 	/* reset counter */
 	cx_write(channel->gpcnt_ctl, 3);
-	q->count = 1;
 
 	/* enable irq */
 	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
@@ -139,86 +99,8 @@ int cx25821_start_video_dma(struct cx25821_dev *dev,
 	return 0;
 }
 
-static int cx25821_restart_video_queue(struct cx25821_dev *dev,
-				       struct cx25821_dmaqueue *q,
-				       const struct sram_channel *channel)
-{
-	struct cx25821_buffer *buf, *prev;
-	struct list_head *item;
-
-	if (!list_empty(&q->active)) {
-		buf = list_entry(q->active.next, struct cx25821_buffer,
-				vb.queue);
-
-		cx25821_start_video_dma(dev, q, buf, channel);
-
-		list_for_each(item, &q->active) {
-			buf = list_entry(item, struct cx25821_buffer, vb.queue);
-			buf->count = q->count++;
-		}
-
-		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-		return 0;
-	}
-
-	prev = NULL;
-	for (;;) {
-		if (list_empty(&q->queued))
-			return 0;
-
-		buf = list_entry(q->queued.next, struct cx25821_buffer,
-				vb.queue);
-
-		if (NULL == prev) {
-			list_move_tail(&buf->vb.queue, &q->active);
-			cx25821_start_video_dma(dev, q, buf, channel);
-			buf->vb.state = VIDEOBUF_ACTIVE;
-			buf->count = q->count++;
-			mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-		} else if (prev->vb.width == buf->vb.width &&
-			   prev->vb.height == buf->vb.height &&
-			   prev->fmt == buf->fmt) {
-			list_move_tail(&buf->vb.queue, &q->active);
-			buf->vb.state = VIDEOBUF_ACTIVE;
-			buf->count = q->count++;
-			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-			prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
-		} else {
-			return 0;
-		}
-		prev = buf;
-	}
-}
-
-static void cx25821_vid_timeout(unsigned long data)
-{
-	struct cx25821_data *timeout_data = (struct cx25821_data *)data;
-	struct cx25821_dev *dev = timeout_data->dev;
-	const struct sram_channel *channel = timeout_data->channel;
-	struct cx25821_dmaqueue *q = &dev->channels[channel->i].dma_vidq;
-	struct cx25821_buffer *buf;
-	unsigned long flags;
-
-	/* cx25821_sram_channel_dump(dev, channel); */
-	cx_clear(channel->dma_ctl, 0x11);
-
-	spin_lock_irqsave(&dev->slock, flags);
-	while (!list_empty(&q->active)) {
-		buf = list_entry(q->active.next, struct cx25821_buffer,
-				vb.queue);
-		list_del(&buf->vb.queue);
-
-		buf->vb.state = VIDEOBUF_ERROR;
-		wake_up(&buf->vb.done);
-	}
-
-	cx25821_restart_video_queue(dev, q, channel);
-	spin_unlock_irqrestore(&dev->slock, flags);
-}
-
 int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
 {
-	u32 count = 0;
 	int handled = 0;
 	u32 mask;
 	const struct sram_channel *channel = dev->channels[chan_num].sram_channels;
@@ -239,317 +121,201 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
 
 	/* risc1 y */
 	if (status & FLD_VID_DST_RISC1) {
-		spin_lock(&dev->slock);
-		count = cx_read(channel->gpcnt);
-		cx25821_video_wakeup(dev, &dev->channels[channel->i].dma_vidq,
-				count);
-		spin_unlock(&dev->slock);
-		handled++;
-	}
+		struct cx25821_dmaqueue *dmaq =
+			&dev->channels[channel->i].dma_vidq;
+		struct cx25821_buffer *buf;
 
-	/* risc2 y */
-	if (status & 0x10) {
-		dprintk(2, "stopper video\n");
 		spin_lock(&dev->slock);
-		cx25821_restart_video_queue(dev,
-				&dev->channels[channel->i].dma_vidq, channel);
+		if (!list_empty(&dmaq->active)) {
+			buf = list_entry(dmaq->active.next,
+					 struct cx25821_buffer, queue);
+
+			v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+			buf->vb.v4l2_buf.sequence = dmaq->count++;
+			list_del(&buf->queue);
+			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+		}
 		spin_unlock(&dev->slock);
 		handled++;
 	}
 	return handled;
 }
 
-static int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
-		 unsigned int *size)
+static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+			   unsigned int *num_buffers, unsigned int *num_planes,
+			   unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct cx25821_channel *chan = q->priv_data;
-
-	*size = chan->fmt->depth * chan->width * chan->height >> 3;
+	struct cx25821_channel *chan = q->drv_priv;
+	unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
 
-	if (0 == *count)
-		*count = 32;
-
-	if (*size * *count > vid_limit * 1024 * 1024)
-		*count = (vid_limit * 1024 * 1024) / *size;
+	if (fmt && fmt->fmt.pix.sizeimage < size)
+		return -EINVAL;
 
+	*num_planes = 1;
+	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size;
+	alloc_ctxs[0] = chan->dev->alloc_ctx;
 	return 0;
 }
 
-static int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-		   enum v4l2_field field)
+static int cx25821_buffer_prepare(struct vb2_buffer *vb)
 {
-	struct cx25821_channel *chan = q->priv_data;
+	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
 	struct cx25821_buffer *buf =
 		container_of(vb, struct cx25821_buffer, vb);
-	int rc, init_buffer = 0;
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	u32 line0_offset;
-	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
 	int bpl_local = LINE_SIZE_D1;
+	int ret;
 
-	BUG_ON(NULL == chan->fmt);
-	if (chan->width < 48 || chan->width > 720 ||
-	    chan->height < 32 || chan->height > 576)
-		return -EINVAL;
-
-	buf->vb.size = (chan->width * chan->height * chan->fmt->depth) >> 3;
+	if (chan->pixel_formats == PIXEL_FRMT_411)
+		buf->bpl = (chan->fmt->depth * chan->width) >> 3;
+	else
+		buf->bpl = (chan->fmt->depth >> 3) * chan->width;
 
-	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+	if (vb2_plane_size(vb, 0) < chan->height * buf->bpl)
 		return -EINVAL;
+	vb2_set_plane_payload(vb, 0, chan->height * buf->bpl);
+	buf->vb.v4l2_buf.field = chan->field;
 
-	if (buf->fmt != chan->fmt ||
-	    buf->vb.width != chan->width ||
-	    buf->vb.height != chan->height || buf->vb.field != field) {
-		buf->fmt = chan->fmt;
-		buf->vb.width = chan->width;
-		buf->vb.height = chan->height;
-		buf->vb.field = field;
-		init_buffer = 1;
-	}
+	if (chan->pixel_formats == PIXEL_FRMT_411) {
+		bpl_local = buf->bpl;
+	} else {
+		bpl_local = buf->bpl;   /* Default */
 
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		init_buffer = 1;
-		rc = videobuf_iolock(q, &buf->vb, NULL);
-		if (0 != rc) {
-			printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
-			goto fail;
+		if (chan->use_cif_resolution) {
+			if (dev->tvnorm & V4L2_STD_625_50)
+				bpl_local = 352 << 1;
+			else
+				bpl_local = chan->cif_width << 1;
 		}
 	}
 
-	dprintk(1, "init_buffer=%d\n", init_buffer);
-
-	if (init_buffer) {
-		if (chan->pixel_formats == PIXEL_FRMT_411)
-			buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
-		else
-			buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
-
-		if (chan->pixel_formats == PIXEL_FRMT_411) {
-			bpl_local = buf->bpl;
-		} else {
-			bpl_local = buf->bpl;   /* Default */
-
-			if (chan->use_cif_resolution) {
-				if (dev->tvnorm & V4L2_STD_625_50)
-					bpl_local = 352 << 1;
-				else
-					bpl_local = chan->cif_width << 1;
-			}
-		}
-
-		switch (buf->vb.field) {
-		case V4L2_FIELD_TOP:
-			cx25821_risc_buffer(dev->pci, &buf->risc,
-					    dma->sglist, 0, UNSET,
-					    buf->bpl, 0, buf->vb.height);
-			break;
-		case V4L2_FIELD_BOTTOM:
-			cx25821_risc_buffer(dev->pci, &buf->risc,
-					    dma->sglist, UNSET, 0,
-					    buf->bpl, 0, buf->vb.height);
-			break;
-		case V4L2_FIELD_INTERLACED:
-			/* All other formats are top field first */
-			line0_offset = 0;
-			dprintk(1, "top field first\n");
-
-			cx25821_risc_buffer(dev->pci, &buf->risc,
-					    dma->sglist, line0_offset,
-					    bpl_local, bpl_local, bpl_local,
-					    buf->vb.height >> 1);
-			break;
-		case V4L2_FIELD_SEQ_TB:
-			cx25821_risc_buffer(dev->pci, &buf->risc,
-					    dma->sglist,
-					    0, buf->bpl * (buf->vb.height >> 1),
-					    buf->bpl, 0, buf->vb.height >> 1);
-			break;
-		case V4L2_FIELD_SEQ_BT:
-			cx25821_risc_buffer(dev->pci, &buf->risc,
-					    dma->sglist,
-					    buf->bpl * (buf->vb.height >> 1), 0,
-					    buf->bpl, 0, buf->vb.height >> 1);
-			break;
-		default:
-			BUG();
-		}
+	switch (chan->field) {
+	case V4L2_FIELD_TOP:
+		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+				sgt->sgl, 0, UNSET,
+				buf->bpl, 0, chan->height);
+		break;
+	case V4L2_FIELD_BOTTOM:
+		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+				sgt->sgl, UNSET, 0,
+				buf->bpl, 0, chan->height);
+		break;
+	case V4L2_FIELD_INTERLACED:
+		/* All other formats are top field first */
+		line0_offset = 0;
+		dprintk(1, "top field first\n");
+
+		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+				sgt->sgl, line0_offset,
+				bpl_local, bpl_local, bpl_local,
+				chan->height >> 1);
+		break;
+	case V4L2_FIELD_SEQ_TB:
+		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+				sgt->sgl,
+				0, buf->bpl * (chan->height >> 1),
+				buf->bpl, 0, chan->height >> 1);
+		break;
+	case V4L2_FIELD_SEQ_BT:
+		ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+				sgt->sgl,
+				buf->bpl * (chan->height >> 1), 0,
+				buf->bpl, 0, chan->height >> 1);
+		break;
+	default:
+		WARN_ON(1);
+		ret = -EINVAL;
+		break;
 	}
 
 	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-		buf, buf->vb.i, chan->width, chan->height, chan->fmt->depth,
-		chan->fmt->name, (unsigned long)buf->risc.dma);
-
-	buf->vb.state = VIDEOBUF_PREPARED;
-
-	return 0;
+		buf, buf->vb.v4l2_buf.index, chan->width, chan->height,
+		chan->fmt->depth, chan->fmt->name,
+		(unsigned long)buf->risc.dma);
 
-fail:
-	cx25821_free_buffer(q, buf);
-	return rc;
+	return ret;
 }
 
-static void cx25821_buffer_release(struct videobuf_queue *q,
-			    struct videobuf_buffer *vb)
+static void cx25821_buffer_finish(struct vb2_buffer *vb)
 {
 	struct cx25821_buffer *buf =
 		container_of(vb, struct cx25821_buffer, vb);
+	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
+	struct cx25821_dev *dev = chan->dev;
 
-	cx25821_free_buffer(q, buf);
-}
-
-static int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	return videobuf_mmap_mapper(&chan->vidq, vma);
+	cx25821_free_buffer(dev, buf);
 }
 
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void cx25821_buffer_queue(struct vb2_buffer *vb)
 {
 	struct cx25821_buffer *buf =
 		container_of(vb, struct cx25821_buffer, vb);
-	struct cx25821_buffer *prev;
-	struct cx25821_channel *chan = vq->priv_data;
+	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
+	struct cx25821_buffer *prev;
 	struct cx25821_dmaqueue *q = &dev->channels[chan->id].dma_vidq;
 
-	/* add jump to stopper */
-	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
-	buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
-
-	dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
-
-	if (!list_empty(&q->queued)) {
-		list_add_tail(&buf->vb.queue, &q->queued);
-		buf->vb.state = VIDEOBUF_QUEUED;
-		dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
-				buf->vb.i);
-
-	} else if (list_empty(&q->active)) {
-		list_add_tail(&buf->vb.queue, &q->active);
-		cx25821_start_video_dma(dev, q, buf, chan->sram_channels);
-		buf->vb.state = VIDEOBUF_ACTIVE;
-		buf->count = q->count++;
-		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-		dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
-				buf, buf->vb.i, buf->count, q->count);
+	buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 12);
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 12);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	if (list_empty(&q->active)) {
+		list_add_tail(&buf->queue, &q->active);
 	} else {
+		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
 		prev = list_entry(q->active.prev, struct cx25821_buffer,
-				vb.queue);
-		if (prev->vb.width == buf->vb.width
-		   && prev->vb.height == buf->vb.height
-		   && prev->fmt == buf->fmt) {
-			list_add_tail(&buf->vb.queue, &q->active);
-			buf->vb.state = VIDEOBUF_ACTIVE;
-			buf->count = q->count++;
-			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-
-			/* 64 bit bits 63-32 */
-			prev->risc.jmp[2] = cpu_to_le32(0);
-			dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
-					buf, buf->vb.i, buf->count);
-
-		} else {
-			list_add_tail(&buf->vb.queue, &q->queued);
-			buf->vb.state = VIDEOBUF_QUEUED;
-			dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
-					buf->vb.i);
-		}
+				queue);
+		list_add_tail(&buf->queue, &q->active);
+		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 	}
-
-	if (list_empty(&q->active))
-		dprintk(2, "active queue empty!\n");
 }
 
-static struct videobuf_queue_ops cx25821_video_qops = {
-	.buf_setup = cx25821_buffer_setup,
-	.buf_prepare = cx25821_buffer_prepare,
-	.buf_queue = buffer_queue,
-	.buf_release = cx25821_buffer_release,
-};
-
-static ssize_t video_read(struct file *file, char __user * data, size_t count,
-			 loff_t *ppos)
+static int cx25821_start_streaming(struct vb2_queue *q, unsigned int count)
 {
-	struct v4l2_fh *fh = file->private_data;
-	struct cx25821_channel *chan = video_drvdata(file);
+	struct cx25821_channel *chan = q->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
-	int err = 0;
-
-	if (mutex_lock_interruptible(&dev->lock))
-		return -ERESTARTSYS;
-	if (chan->streaming_fh && chan->streaming_fh != fh) {
-		err = -EBUSY;
-		goto unlock;
-	}
-	chan->streaming_fh = fh;
+	struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq;
+	struct cx25821_buffer *buf = list_entry(dmaq->active.next,
+			struct cx25821_buffer, queue);
 
-	err = videobuf_read_one(&chan->vidq, data, count, ppos,
-				file->f_flags & O_NONBLOCK);
-unlock:
-	mutex_unlock(&dev->lock);
-	return err;
-}
-
-static unsigned int video_poll(struct file *file,
-			      struct poll_table_struct *wait)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-	unsigned long req_events = poll_requested_events(wait);
-	unsigned int res = v4l2_ctrl_poll(file, wait);
-
-	if (req_events & (POLLIN | POLLRDNORM))
-		res |= videobuf_poll_stream(file, &chan->vidq, wait);
-	return res;
-
-	/* This doesn't belong in poll(). This can be done
-	 * much better with vb2. We keep this code here as a
-	 * reminder.
-	if ((res & POLLIN) && buf->vb.state == VIDEOBUF_DONE) {
-		struct cx25821_dev *dev = chan->dev;
-
-		if (dev && chan->use_cif_resolution) {
-			u8 cam_id = *((char *)buf->vb.baddr + 3);
-			memcpy((char *)buf->vb.baddr,
-					(char *)buf->vb.baddr + (chan->width * 2),
-					(chan->width * 2));
-			*((char *)buf->vb.baddr + 3) = cam_id;
-		}
-	}
-	 */
+	dmaq->count = 0;
+	cx25821_start_video_dma(dev, dmaq, buf, chan->sram_channels);
+	return 0;
 }
 
-static int video_release(struct file *file)
+static void cx25821_stop_streaming(struct vb2_queue *q)
 {
-	struct cx25821_channel *chan = video_drvdata(file);
-	struct v4l2_fh *fh = file->private_data;
+	struct cx25821_channel *chan = q->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
-	const struct sram_channel *sram_ch =
-		dev->channels[0].sram_channels;
-
-	mutex_lock(&dev->lock);
-	/* stop the risc engine and fifo */
-	cx_write(sram_ch->dma_ctl, 0); /* FIFO and RISC disable */
+	struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq;
+	unsigned long flags;
 
-	/* stop video capture */
-	if (chan->streaming_fh == fh) {
-		videobuf_queue_cancel(&chan->vidq);
-		chan->streaming_fh = NULL;
-	}
+	cx_write(chan->sram_channels->dma_ctl, 0); /* FIFO and RISC disable */
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&dmaq->active)) {
+		struct cx25821_buffer *buf = list_entry(dmaq->active.next,
+			struct cx25821_buffer, queue);
 
-	if (chan->vidq.read_buf) {
-		cx25821_buffer_release(&chan->vidq, chan->vidq.read_buf);
-		kfree(chan->vidq.read_buf);
+		list_del(&buf->queue);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	}
-
-	videobuf_mmap_free(&chan->vidq);
-	mutex_unlock(&dev->lock);
-
-	return v4l2_fh_release(file);
+	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
+static struct vb2_ops cx25821_video_qops = {
+	.queue_setup    = cx25821_queue_setup,
+	.buf_prepare  = cx25821_buffer_prepare,
+	.buf_finish = cx25821_buffer_finish,
+	.buf_queue    = cx25821_buffer_queue,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = cx25821_start_streaming,
+	.stop_streaming = cx25821_stop_streaming,
+};
+
 /* VIDEO IOCTLS */
 
 static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
@@ -571,7 +337,7 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 
 	f->fmt.pix.width = chan->width;
 	f->fmt.pix.height = chan->height;
-	f->fmt.pix.field = chan->vidq.field;
+	f->fmt.pix.field = chan->field;
 	f->fmt.pix.pixelformat = chan->fmt->fourcc;
 	f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
@@ -632,7 +398,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 		return err;
 
 	chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
-	chan->vidq.field = f->fmt.pix.field;
+	chan->field = f->fmt.pix.field;
 	chan->width = f->fmt.pix.width;
 	chan->height = f->fmt.pix.height;
 
@@ -654,47 +420,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	if (chan->streaming_fh && chan->streaming_fh != priv)
-		return -EBUSY;
-	chan->streaming_fh = priv;
-
-	return videobuf_streamon(&chan->vidq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	if (chan->streaming_fh && chan->streaming_fh != priv)
-		return -EBUSY;
-	if (chan->streaming_fh == NULL)
-		return 0;
-
-	chan->streaming_fh = NULL;
-	return videobuf_streamoff(&chan->vidq);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	int ret_val = 0;
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	ret_val = videobuf_dqbuf(&chan->vidq, p, file->f_flags & O_NONBLOCK);
-	p->sequence = chan->dma_vidq.count;
-
-	return ret_val;
-}
-
 static int vidioc_log_status(struct file *file, void *priv)
 {
 	struct cx25821_channel *chan = video_drvdata(file);
@@ -729,29 +454,6 @@ static int cx25821_vidioc_querycap(struct file *file, void *priv,
 	return 0;
 }
 
-static int cx25821_vidioc_reqbufs(struct file *file, void *priv,
-			   struct v4l2_requestbuffers *p)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	return videobuf_reqbufs(&chan->vidq, p);
-}
-
-static int cx25821_vidioc_querybuf(struct file *file, void *priv,
-			    struct v4l2_buffer *p)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	return videobuf_querybuf(&chan->vidq, p);
-}
-
-static int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-
-	return videobuf_qbuf(&chan->vidq, p);
-}
-
 static int cx25821_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
 {
 	struct cx25821_channel *chan = video_drvdata(file);
@@ -880,7 +582,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 		return err;
 
 	chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
-	chan->vidq.field = f->fmt.pix.field;
+	chan->field = f->fmt.pix.field;
 	chan->width = f->fmt.pix.width;
 	chan->height = f->fmt.pix.height;
 	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
@@ -890,52 +592,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 	return 0;
 }
 
-static ssize_t video_write(struct file *file, const char __user *data, size_t count,
-			 loff_t *ppos)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-	struct cx25821_dev *dev = chan->dev;
-	struct v4l2_fh *fh = file->private_data;
-	int err = 0;
-
-	if (mutex_lock_interruptible(&dev->lock))
-		return -ERESTARTSYS;
-	if (chan->streaming_fh && chan->streaming_fh != fh) {
-		err = -EBUSY;
-		goto unlock;
-	}
-	if (!chan->streaming_fh) {
-		err = cx25821_vidupstream_init(chan, chan->pixel_formats);
-		if (err)
-			goto unlock;
-		chan->streaming_fh = fh;
-	}
-
-	err = cx25821_write_frame(chan, data, count);
-	count -= err;
-	*ppos += err;
-
-unlock:
-	mutex_unlock(&dev->lock);
-	return err;
-}
-
-static int video_out_release(struct file *file)
-{
-	struct cx25821_channel *chan = video_drvdata(file);
-	struct cx25821_dev *dev = chan->dev;
-	struct v4l2_fh *fh = file->private_data;
-
-	mutex_lock(&dev->lock);
-	if (chan->streaming_fh == fh) {
-		cx25821_stop_upstream_video(chan);
-		chan->streaming_fh = NULL;
-	}
-	mutex_unlock(&dev->lock);
-
-	return v4l2_fh_release(file);
-}
-
 static const struct v4l2_ctrl_ops cx25821_ctrl_ops = {
 	.s_ctrl = cx25821_s_ctrl,
 };
@@ -943,11 +599,11 @@ static const struct v4l2_ctrl_ops cx25821_ctrl_ops = {
 static const struct v4l2_file_operations video_fops = {
 	.owner = THIS_MODULE,
 	.open = v4l2_fh_open,
-	.release = video_release,
-	.read = video_read,
-	.poll = video_poll,
-	.mmap = cx25821_video_mmap,
+	.release        = vb2_fop_release,
+	.read           = vb2_fop_read,
+	.poll		= vb2_fop_poll,
 	.unlocked_ioctl = video_ioctl2,
+	.mmap           = vb2_fop_mmap,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -956,17 +612,19 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
-	.vidioc_reqbufs = cx25821_vidioc_reqbufs,
-	.vidioc_querybuf = cx25821_vidioc_querybuf,
-	.vidioc_qbuf = cx25821_vidioc_qbuf,
-	.vidioc_dqbuf = vidioc_dqbuf,
+	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
+	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
+	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
+	.vidioc_querybuf      = vb2_ioctl_querybuf,
+	.vidioc_qbuf          = vb2_ioctl_qbuf,
+	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
+	.vidioc_streamon      = vb2_ioctl_streamon,
+	.vidioc_streamoff     = vb2_ioctl_streamoff,
 	.vidioc_g_std = cx25821_vidioc_g_std,
 	.vidioc_s_std = cx25821_vidioc_s_std,
 	.vidioc_enum_input = cx25821_vidioc_enum_input,
 	.vidioc_g_input = cx25821_vidioc_g_input,
 	.vidioc_s_input = cx25821_vidioc_s_input,
-	.vidioc_streamon = vidioc_streamon,
-	.vidioc_streamoff = vidioc_streamoff,
 	.vidioc_log_status = vidioc_log_status,
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
@@ -984,9 +642,11 @@ static const struct video_device cx25821_video_device = {
 static const struct v4l2_file_operations video_out_fops = {
 	.owner = THIS_MODULE,
 	.open = v4l2_fh_open,
-	.write = video_write,
-	.release = video_out_release,
+	.release        = vb2_fop_release,
+	.write          = vb2_fop_write,
+	.poll		= vb2_fop_poll,
 	.unlocked_ioctl = video_ioctl2,
+	.mmap           = vb2_fop_mmap,
 };
 
 static const struct v4l2_ioctl_ops video_out_ioctl_ops = {
@@ -1019,9 +679,6 @@ void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
 	if (video_is_registered(&dev->channels[chan_num].vdev)) {
 		video_unregister_device(&dev->channels[chan_num].vdev);
 		v4l2_ctrl_handler_free(&dev->channels[chan_num].hdl);
-
-		btcx_riscmem_free(dev->pci,
-				&dev->channels[chan_num].dma_vidq.stopper);
 	}
 }
 
@@ -1035,10 +692,11 @@ int cx25821_video_register(struct cx25821_dev *dev)
 
 	spin_lock_init(&dev->slock);
 
-	for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+	for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; ++i) {
 		struct cx25821_channel *chan = &dev->channels[i];
 		struct video_device *vdev = &chan->vdev;
 		struct v4l2_ctrl_handler *hdl = &chan->hdl;
+		struct vb2_queue *q;
 		bool is_output = i > SRAM_CH08;
 
 		if (i == SRAM_CH08) /* audio channel */
@@ -1066,11 +724,9 @@ int cx25821_video_register(struct cx25821_dev *dev)
 			chan->out->chan = chan;
 		}
 
-		cx25821_risc_stopper(dev->pci, &chan->dma_vidq.stopper,
-			chan->sram_channels->dma_ctl, 0x11, 0);
-
 		chan->sram_channels = &cx25821_sram_channels[i];
 		chan->width = 720;
+		chan->field = V4L2_FIELD_INTERLACED;
 		if (dev->tvnorm & V4L2_STD_625_50)
 			chan->height = 576;
 		else
@@ -1084,19 +740,27 @@ int cx25821_video_register(struct cx25821_dev *dev)
 		cx_write(chan->sram_channels->int_stat, 0xffffffff);
 
 		INIT_LIST_HEAD(&chan->dma_vidq.active);
-		INIT_LIST_HEAD(&chan->dma_vidq.queued);
 
-		chan->timeout_data.dev = dev;
-		chan->timeout_data.channel = &cx25821_sram_channels[i];
-		chan->dma_vidq.timeout.function = cx25821_vid_timeout;
-		chan->dma_vidq.timeout.data = (unsigned long)&chan->timeout_data;
-		init_timer(&chan->dma_vidq.timeout);
+		q = &chan->vidq;
+
+		q->type = is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT :
+				      V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+		q->io_modes |= is_output ? VB2_WRITE : VB2_READ;
+		q->gfp_flags = GFP_DMA32;
+		q->min_buffers_needed = 2;
+		q->drv_priv = chan;
+		q->buf_struct_size = sizeof(struct cx25821_buffer);
+		q->ops = &cx25821_video_qops;
+		q->mem_ops = &vb2_dma_sg_memops;
+		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+		q->lock = &dev->lock;
 
-		if (!is_output)
-			videobuf_queue_sg_init(&chan->vidq, &cx25821_video_qops, &dev->pci->dev,
-				&dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer),
-				chan, &dev->lock);
+		if (!is_output) {
+			err = vb2_queue_init(q);
+			if (err < 0)
+				goto fail_unreg;
+		}
 
 		/* register v4l devices */
 		*vdev = is_output ? cx25821_video_out_device : cx25821_video_device;
@@ -1106,6 +770,7 @@ int cx25821_video_register(struct cx25821_dev *dev)
 		else
 			vdev->vfl_dir = VFL_DIR_TX;
 		vdev->lock = &dev->lock;
+		vdev->queue = q;
 		snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
 		video_set_drvdata(vdev, chan);
 
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
index 90bdc196929f..d81a08a2df4f 100644
--- a/drivers/media/pci/cx25821/cx25821.h
+++ b/drivers/media/pci/cx25821/cx25821.h
@@ -34,9 +34,8 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf2-dma-sg.h>
 
-#include "btcx-risc.h"
 #include "cx25821-reg.h"
 #include "cx25821-medusa-reg.h"
 #include "cx25821-sram.h"
@@ -89,6 +88,13 @@
 
 #define CX25821_BOARD_CONEXANT_ATHENA10 1
 #define MAX_VID_CHANNEL_NUM     12
+
+/*
+ * Maximum capture-only channels. This can go away once video/audio output
+ * is fully supported in this driver.
+ */
+#define MAX_VID_CAP_CHANNEL_NUM     10
+
 #define VID_CHANNEL_NUM 8
 
 struct cx25821_fmt {
@@ -111,16 +117,23 @@ enum cx25821_src_sel_type {
 	CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
 };
 
+struct cx25821_riscmem {
+	unsigned int   size;
+	__le32         *cpu;
+	__le32         *jmp;
+	dma_addr_t     dma;
+};
+
 /* buffer for one video frame */
 struct cx25821_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer vb;
+	struct vb2_buffer vb;
+	struct list_head queue;
 
 	/* cx25821 specific */
 	unsigned int bpl;
-	struct btcx_riscmem risc;
+	struct cx25821_riscmem risc;
 	const struct cx25821_fmt *fmt;
-	u32 count;
 };
 
 enum port {
@@ -159,17 +172,9 @@ struct cx25821_i2c {
 
 struct cx25821_dmaqueue {
 	struct list_head active;
-	struct list_head queued;
-	struct timer_list timeout;
-	struct btcx_riscmem stopper;
 	u32 count;
 };
 
-struct cx25821_data {
-	struct cx25821_dev *dev;
-	const struct sram_channel *channel;
-};
-
 struct cx25821_dev;
 
 struct cx25821_channel;
@@ -207,18 +212,17 @@ struct cx25821_video_out_data {
 struct cx25821_channel {
 	unsigned id;
 	struct cx25821_dev *dev;
-	struct v4l2_fh *streaming_fh;
 
 	struct v4l2_ctrl_handler hdl;
-	struct cx25821_data timeout_data;
 
 	struct video_device vdev;
 	struct cx25821_dmaqueue dma_vidq;
-	struct videobuf_queue vidq;
+	struct vb2_queue vidq;
 
 	const struct sram_channel *sram_channels;
 
 	const struct cx25821_fmt *fmt;
+	unsigned field;
 	unsigned int width, height;
 	int pixel_formats;
 	int use_cif_resolution;
@@ -244,6 +248,7 @@ struct cx25821_dev {
 	int hwrevision;
 	/* used by cx25821-alsa */
 	struct snd_card *card;
+	void *alloc_ctx;
 
 	u32 clk_freq;
 
@@ -405,21 +410,22 @@ extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
 				      const struct sram_channel *ch, unsigned int bpl,
 				      u32 risc);
 
-extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+extern int cx25821_riscmem_alloc(struct pci_dev *pci,
+				 struct cx25821_riscmem *risc,
+				 unsigned int size);
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc,
 			       struct scatterlist *sglist,
 			       unsigned int top_offset,
 			       unsigned int bottom_offset,
 			       unsigned int bpl,
 			       unsigned int padding, unsigned int lines);
 extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
-					 struct btcx_riscmem *risc,
+					 struct cx25821_riscmem *risc,
 					 struct scatterlist *sglist,
 					 unsigned int bpl,
 					 unsigned int lines, unsigned int lpi);
-extern void cx25821_free_buffer(struct videobuf_queue *q,
+extern void cx25821_free_buffer(struct cx25821_dev *dev,
 				struct cx25821_buffer *buf);
-extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-				u32 reg, u32 mask, u32 value);
 extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
 				      const struct sram_channel *ch);
 extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index d3c79d964f2c..b6be46e94289 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -1234,6 +1234,3 @@ static void __exit blackbird_fini(void)
 
 module_init(blackbird_init);
 module_exit(blackbird_fini);
-
-module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages [video]");
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index dee177ed5fe9..c38d5a12e277 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -1091,10 +1091,3 @@ EXPORT_SYMBOL(cx88_core_put);
 
 EXPORT_SYMBOL(cx88_ir_start);
 EXPORT_SYMBOL(cx88_ir_stop);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 5780e2f013b4..1b2ed238cdb6 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -1504,8 +1504,8 @@ static int dvb_register(struct cx8802_dev *dev)
 			fe0->dvb.frontend = dvb_attach(stv0288_attach,
 							    &tevii_tuner_earda_config,
 							    &core->i2c_adap);
-				if (fe0->dvb.frontend != NULL) {
-					if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
 						&core->i2c_adap))
 					goto frontend_detach;
 				core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 1c1f69e6b0b9..a369b0840acf 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -833,10 +833,3 @@ EXPORT_SYMBOL(cx8802_start_dma);
 EXPORT_SYMBOL(cx8802_register_driver);
 EXPORT_SYMBOL(cx8802_unregister_driver);
 EXPORT_SYMBOL(cx8802_get_driver);
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/pci/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c
index 424fd97495dc..6bbce6ad6295 100644
--- a/drivers/media/pci/cx88/cx88-tvaudio.c
+++ b/drivers/media/pci/cx88/cx88-tvaudio.c
@@ -1050,10 +1050,3 @@ EXPORT_SYMBOL(cx88_newstation);
 EXPORT_SYMBOL(cx88_set_stereo);
 EXPORT_SYMBOL(cx88_get_stereo);
 EXPORT_SYMBOL(cx88_audio_thread);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c
index ab6d5d25aa6f..e7d701777e53 100644
--- a/drivers/media/pci/ivtv/ivtv-irq.c
+++ b/drivers/media/pci/ivtv/ivtv-irq.c
@@ -357,7 +357,6 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
 	u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
 	int y_done = 0;
 	int bytes_written = 0;
-	unsigned long flags = 0;
 	int idx = 0;
 
 	IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
@@ -407,16 +406,21 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
 
 	/* Sync Hardware SG List of buffers */
 	ivtv_stream_sync_for_device(s);
-	if (lock)
+	if (lock) {
+		unsigned long flags = 0;
+
 		spin_lock_irqsave(&itv->dma_reg_lock, flags);
-	if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
-		ivtv_dma_dec_start(s);
-	}
-	else {
-		set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
-	}
-	if (lock)
+		if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
+			ivtv_dma_dec_start(s);
+		else
+			set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
 		spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
+	} else {
+		if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
+			ivtv_dma_dec_start(s);
+		else
+			set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
+	}
 }
 
 static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
diff --git a/drivers/media/pci/mantis/mantis_core.c b/drivers/media/pci/mantis/mantis_core.c
index 684d9061fe2a..82220ea72dd3 100644
--- a/drivers/media/pci/mantis/mantis_core.c
+++ b/drivers/media/pci/mantis/mantis_core.c
@@ -56,29 +56,6 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
 	return 0;
 }
 
-static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
-{
-	int err;
-
-	struct i2c_msg msg = {
-		.addr = 0x50,
-		.flags = 0,
-		.buf = data,
-		.len = length
-	};
-
-	err = i2c_transfer(&mantis->adapter, &msg, 1);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1,
-			"ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
-			err, length, data[0], data[1]);
-
-		return err;
-	}
-
-	return 0;
-}
-
 static int get_mac_address(struct mantis_pci *mantis)
 {
 	int err;
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 701b52f34689..99d09a7566d3 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1084,11 +1084,6 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
 
 /* ------------------------------------------------------------------ */
 
-static inline struct vb2_queue *saa7134_queue(struct file *file)
-{
-	return video_devdata(file)->queue;
-}
-
 static int video_open(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie.c
index f773350e67b9..36c8ed77309c 100644
--- a/drivers/media/pci/smipcie/smipcie.c
+++ b/drivers/media/pci/smipcie/smipcie.c
@@ -448,16 +448,19 @@ static void smi_port_exit(struct smi_port *port)
 	port->enable = 0;
 }
 
-static void smi_port_irq(struct smi_port *port, u32 int_status)
+static int smi_port_irq(struct smi_port *port, u32 int_status)
 {
 	u32 port_req_irq = port->_dmaInterruptCH0 | port->_dmaInterruptCH1;
+	int handled = 0;
 
 	if (int_status & port_req_irq) {
 		smi_port_disableInterrupt(port);
 		port->_int_status = int_status;
 		smi_port_clearInterrupt(port);
 		tasklet_schedule(&port->tasklet);
+		handled = 1;
 	}
+	return handled;
 }
 
 static irqreturn_t smi_irq_handler(int irq, void *dev_id)
@@ -465,18 +468,19 @@ static irqreturn_t smi_irq_handler(int irq, void *dev_id)
 	struct smi_dev *dev = dev_id;
 	struct smi_port *port0 = &dev->ts_port[0];
 	struct smi_port *port1 = &dev->ts_port[1];
+	int handled = 0;
 
 	u32 intr_status = smi_read(MSI_INT_STATUS);
 
 	/* ts0 interrupt.*/
 	if (dev->info->ts_0)
-		smi_port_irq(port0, intr_status);
+		handled += smi_port_irq(port0, intr_status);
 
 	/* ts1 interrupt.*/
 	if (dev->info->ts_1)
-		smi_port_irq(port1, intr_status);
+		handled += smi_port_irq(port1, intr_status);
 
-	return IRQ_HANDLED;
+	return IRQ_RETVAL(handled);
 }
 
 static struct i2c_client *smi_add_i2c_client(struct i2c_adapter *adapter,
diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c
index 8cbe6b49f4c2..570d119ea18b 100644
--- a/drivers/media/pci/solo6x10/solo6x10-core.c
+++ b/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -182,7 +182,7 @@ static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
 {
 	struct solo_dev *solo_dev =
 		container_of(dev, struct solo_dev, dev);
-	unsigned short *p = (unsigned short *)buf;
+	u16 *p = (u16 *)buf;
 	int i;
 
 	if (count & 0x1)
@@ -212,7 +212,7 @@ static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
 {
 	struct solo_dev *solo_dev =
 		container_of(dev, struct solo_dev, dev);
-	unsigned short *p = (unsigned short *)buf;
+	u16 *p = (u16 *)buf;
 	int count = (full_eeprom ? 128 : 64);
 	int i;
 
diff --git a/drivers/media/pci/solo6x10/solo6x10-eeprom.c b/drivers/media/pci/solo6x10/solo6x10-eeprom.c
index da25ce4a6952..8e81186dc785 100644
--- a/drivers/media/pci/solo6x10/solo6x10-eeprom.c
+++ b/drivers/media/pci/solo6x10/solo6x10-eeprom.c
@@ -103,7 +103,7 @@ unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
 __be16 solo_eeprom_read(struct solo_dev *solo_dev, int loc)
 {
 	int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
-	unsigned short retval = 0;
+	u16 retval = 0;
 	int i;
 
 	solo_eeprom_cmd(solo_dev, read_cmd);
diff --git a/drivers/media/pci/solo6x10/solo6x10-enc.c b/drivers/media/pci/solo6x10/solo6x10-enc.c
index d19c0aef5abc..d28211bb9674 100644
--- a/drivers/media/pci/solo6x10/solo6x10-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-enc.c
@@ -136,11 +136,11 @@ static void solo_capture_config(struct solo_dev *solo_dev)
 int solo_osd_print(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	unsigned char *str = solo_enc->osd_text;
+	u8 *str = solo_enc->osd_text;
 	u8 *buf = solo_enc->osd_buf;
 	u32 reg;
 	const struct font_desc *vga = find_font("VGA8x16");
-	const unsigned char *vga_data;
+	const u8 *vga_data;
 	int i, j;
 
 	if (WARN_ON_ONCE(!vga))
@@ -154,7 +154,7 @@ int solo_osd_print(struct solo_enc_dev *solo_enc)
 	}
 
 	memset(buf, 0, SOLO_OSD_WRITE_SIZE);
-	vga_data = (const unsigned char *)vga->data;
+	vga_data = (const u8 *)vga->data;
 
 	for (i = 0; *str; i++, str++) {
 		for (j = 0; j < 16; j++) {
diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c
index c7141f2e63bd..7ddc76709caa 100644
--- a/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -56,8 +56,8 @@
 struct solo_snd_pcm {
 	int				on;
 	spinlock_t			lock;
-	struct solo_dev		*solo_dev;
-	unsigned char			*g723_buf;
+	struct solo_dev			*solo_dev;
+	u8				*g723_buf;
 	dma_addr_t			g723_dma;
 };
 
diff --git a/drivers/media/pci/solo6x10/solo6x10-jpeg.h b/drivers/media/pci/solo6x10/solo6x10-jpeg.h
index 1c66a46da514..3c611bd3f2d8 100644
--- a/drivers/media/pci/solo6x10/solo6x10-jpeg.h
+++ b/drivers/media/pci/solo6x10/solo6x10-jpeg.h
@@ -21,7 +21,7 @@
 #ifndef __SOLO6X10_JPEG_H
 #define __SOLO6X10_JPEG_H
 
-static const unsigned char jpeg_header[] = {
+static const u8 jpeg_header[] = {
 	0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
 	0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
 	0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
@@ -106,7 +106,7 @@ static const unsigned char jpeg_header[] = {
 /* This is the byte marker for the start of the DQT */
 #define DQT_START	17
 #define DQT_LEN		138
-static const unsigned char jpeg_dqt[4][DQT_LEN] = {
+static const u8 jpeg_dqt[4][DQT_LEN] = {
 	{
 		0xff, 0xdb, 0x00, 0x43, 0x00,
 		0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
diff --git a/drivers/media/pci/solo6x10/solo6x10-tw28.c b/drivers/media/pci/solo6x10/solo6x10-tw28.c
index edd0781ee4b5..0632d3f7c73c 100644
--- a/drivers/media/pci/solo6x10/solo6x10-tw28.c
+++ b/drivers/media/pci/solo6x10/solo6x10-tw28.c
@@ -510,7 +510,7 @@ static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr)
 #define FIRST_ACTIVE_LINE	0x0008
 #define LAST_ACTIVE_LINE	0x0102
 
-static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals,
+static void saa712x_write_regs(struct solo_dev *dev, const u8 *vals,
 		int start, int n)
 {
 	for (; start < n; start++, vals++) {
@@ -532,7 +532,7 @@ static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals,
 static void saa712x_setup(struct solo_dev *dev)
 {
 	const int reg_start = 0x26;
-	const uint8_t saa7128_regs_ntsc[] = {
+	const u8 saa7128_regs_ntsc[] = {
 	/* :0x26 */
 		0x0d, 0x00,
 	/* :0x28 */
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 6e933d383fa2..53fff5425c13 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -38,28 +38,28 @@
 #define DMA_ALIGN		4096
 
 /* 6010 M4V */
-static unsigned char vop_6010_ntsc_d1[] = {
+static u8 vop_6010_ntsc_d1[] = {
 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
 	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
 	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
 	0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
 };
 
-static unsigned char vop_6010_ntsc_cif[] = {
+static u8 vop_6010_ntsc_cif[] = {
 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
 	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
 	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
 	0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
 };
 
-static unsigned char vop_6010_pal_d1[] = {
+static u8 vop_6010_pal_d1[] = {
 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
 	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
 	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
 	0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
 };
 
-static unsigned char vop_6010_pal_cif[] = {
+static u8 vop_6010_pal_cif[] = {
 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
 	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
 	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
@@ -67,25 +67,25 @@ static unsigned char vop_6010_pal_cif[] = {
 };
 
 /* 6110 h.264 */
-static unsigned char vop_6110_ntsc_d1[] = {
+static u8 vop_6110_ntsc_d1[] = {
 	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
 	0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
 	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
 };
 
-static unsigned char vop_6110_ntsc_cif[] = {
+static u8 vop_6110_ntsc_cif[] = {
 	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
 	0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
 	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
 };
 
-static unsigned char vop_6110_pal_d1[] = {
+static u8 vop_6110_pal_d1[] = {
 	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
 	0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
 	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
 };
 
-static unsigned char vop_6110_pal_cif[] = {
+static u8 vop_6110_pal_cif[] = {
 	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
 	0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
 	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
@@ -149,7 +149,7 @@ void solo_update_mode(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	int vop_len;
-	unsigned char *vop;
+	u8 *vop;
 
 	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
 	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
@@ -239,8 +239,6 @@ static int solo_enc_on(struct solo_enc_dev *solo_enc)
 	if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
 		return -EBUSY;
 	solo_enc->sequence = 0;
-	solo_enc->motion_last_state = false;
-	solo_enc->frames_since_last_motion = 0;
 	solo_dev->enc_bw_remain -= solo_enc->bw_weight;
 
 	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
@@ -529,36 +527,12 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
 	}
 
 	if (!ret) {
-		bool send_event = false;
-
 		vb->v4l2_buf.sequence = solo_enc->sequence++;
 		vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
 		vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
 
 		/* Check for motion flags */
-		if (solo_is_motion_on(solo_enc)) {
-			/* It takes a few frames for the hardware to detect
-			 * motion. Once it does it clears the motion detection
-			 * register and it takes again a few frames before
-			 * motion is seen. This means in practice that when the
-			 * motion field is 1, it will go back to 0 for the next
-			 * frame. This leads to motion detection event being
-			 * sent all the time, which is not what we want.
-			 * Instead wait a few frames before deciding that the
-			 * motion has halted. After some experimentation it
-			 * turns out that waiting for 5 frames works well.
-			 */
-			if (enc_buf->motion == 0 &&
-			    solo_enc->motion_last_state &&
-			    solo_enc->frames_since_last_motion++ > 5)
-				send_event = true;
-			else if (enc_buf->motion) {
-				solo_enc->frames_since_last_motion = 0;
-				send_event = !solo_enc->motion_last_state;
-			}
-		}
-
-		if (send_event) {
+		if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
 			struct v4l2_event ev = {
 				.type = V4L2_EVENT_MOTION_DET,
 				.u.motion_det = {
@@ -568,8 +542,6 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
 				},
 			};
 
-			solo_enc->motion_last_state = enc_buf->motion;
-			solo_enc->frames_since_last_motion = 0;
 			v4l2_event_queue(solo_enc->vfd, &ev);
 		}
 	}
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index bd8edfa319b8..1ca54b08b3aa 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -159,8 +159,6 @@ struct solo_enc_dev {
 	u16			motion_thresh;
 	bool			motion_global;
 	bool			motion_enabled;
-	bool			motion_last_state;
-	u8			frames_since_last_motion;
 	u16			width;
 	u16			height;
 
@@ -170,9 +168,9 @@ struct solo_enc_dev {
 					__aligned(4);
 
 	/* VOP stuff */
-	unsigned char		vop[64];
+	u8			vop[64];
 	int			vop_len;
-	unsigned char		jpeg_header[1024];
+	u8			jpeg_header[1024];
 	int			jpeg_len;
 
 	u32			fmt;
diff --git a/drivers/media/pci/sta2x11/Kconfig b/drivers/media/pci/sta2x11/Kconfig
index f6f30abc088b..e03587b1af71 100644
--- a/drivers/media/pci/sta2x11/Kconfig
+++ b/drivers/media/pci/sta2x11/Kconfig
@@ -5,6 +5,7 @@ config STA2X11_VIP
 	select VIDEO_ADV7180 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEOBUF2_DMA_CONTIG
 	depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS
+	depends on VIDEO_V4L2_SUBDEV_API
 	depends on I2C
 	help
 	  Say Y for support for STA2X11 VIP (Video Input Port) capture
diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c
index c1f0617a6973..45199a12b9d9 100644
--- a/drivers/media/pci/ttpci/av7110.c
+++ b/drivers/media/pci/ttpci/av7110.c
@@ -1219,11 +1219,14 @@ static int stop_ts_capture(struct av7110 *budget)
 
 static int start_ts_capture(struct av7110 *budget)
 {
+	unsigned y;
+
 	dprintk(2, "budget: %p\n", budget);
 
 	if (budget->feeding1)
 		return ++budget->feeding1;
-	memset(budget->grabbing, 0x00, TS_BUFLEN);
+	for (y = 0; y < TS_HEIGHT; y++)
+		memset(budget->grabbing + y * TS_WIDTH, 0x00, TS_WIDTH);
 	budget->ttbp = 0;
 	SAA7146_ISR_CLEAR(budget->dev, MASK_10);  /* VPE */
 	SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c
index 37d02fe09137..23e05499b509 100644
--- a/drivers/media/pci/ttpci/budget-core.c
+++ b/drivers/media/pci/ttpci/budget-core.c
@@ -231,63 +231,59 @@ static void vpeirq(unsigned long data)
 }
 
 
-int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
-			  int uselocks, int nobusyloop)
+static int ttpci_budget_debiread_nolock(struct budget *budget, u32 config,
+		int addr, int count, int nobusyloop)
 {
 	struct saa7146_dev *saa = budget->dev;
-	int result = 0;
-	unsigned long flags = 0;
-
-	if (count > 4 || count <= 0)
-		return 0;
-
-	if (uselocks)
-		spin_lock_irqsave(&budget->debilock, flags);
+	int result;
 
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
+	result = saa7146_wait_for_debi_done(saa, nobusyloop);
+	if (result < 0)
 		return result;
-	}
 
 	saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
 	saa7146_write(saa, DEBI_CONFIG, config);
 	saa7146_write(saa, DEBI_PAGE, 0);
 	saa7146_write(saa, MC2, (2 << 16) | 2);
 
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
+	result = saa7146_wait_for_debi_done(saa, nobusyloop);
+	if (result < 0)
 		return result;
-	}
 
 	result = saa7146_read(saa, DEBI_AD);
 	result &= (0xffffffffUL >> ((4 - count) * 8));
-
-	if (uselocks)
-		spin_unlock_irqrestore(&budget->debilock, flags);
-
 	return result;
 }
 
-int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
-			   int count, u32 value, int uselocks, int nobusyloop)
+int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
+			  int uselocks, int nobusyloop)
 {
-	struct saa7146_dev *saa = budget->dev;
-	unsigned long flags = 0;
-	int result;
-
 	if (count > 4 || count <= 0)
 		return 0;
 
-	if (uselocks)
-		spin_lock_irqsave(&budget->debilock, flags);
+	if (uselocks) {
+		unsigned long flags;
+		int result;
 
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
+		spin_lock_irqsave(&budget->debilock, flags);
+		result = ttpci_budget_debiread_nolock(budget, config, addr,
+						      count, nobusyloop);
+		spin_unlock_irqrestore(&budget->debilock, flags);
 		return result;
 	}
+	return ttpci_budget_debiread_nolock(budget, config, addr,
+					    count, nobusyloop);
+}
+
+static int ttpci_budget_debiwrite_nolock(struct budget *budget, u32 config,
+		int addr, int count, u32 value, int nobusyloop)
+{
+	struct saa7146_dev *saa = budget->dev;
+	int result;
+
+	result = saa7146_wait_for_debi_done(saa, nobusyloop);
+	if (result < 0)
+		return result;
 
 	saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff));
 	saa7146_write(saa, DEBI_CONFIG, config);
@@ -295,15 +291,28 @@ int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
 	saa7146_write(saa, DEBI_AD, value);
 	saa7146_write(saa, MC2, (2 << 16) | 2);
 
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
-		return result;
-	}
+	result = saa7146_wait_for_debi_done(saa, nobusyloop);
+	return result < 0 ? result : 0;
+}
 
-	if (uselocks)
+int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
+			   int count, u32 value, int uselocks, int nobusyloop)
+{
+	if (count > 4 || count <= 0)
+		return 0;
+
+	if (uselocks) {
+		unsigned long flags;
+		int result;
+
+		spin_lock_irqsave(&budget->debilock, flags);
+		result = ttpci_budget_debiwrite_nolock(budget, config, addr,
+						count, value, nobusyloop);
 		spin_unlock_irqrestore(&budget->debilock, flags);
-	return 0;
+		return result;
+	}
+	return ttpci_budget_debiwrite_nolock(budget, config, addr,
+					     count, value, nobusyloop);
 }
 
 
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index 7a7501bd165f..93f2335e004b 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -25,7 +25,6 @@
  *  GNU General Public License for more details.
  */
 
-#include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <linux/notifier.h>
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 765bffb49a72..d9b872b9285a 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -56,10 +56,8 @@ config VIDEO_VIU
 
 config VIDEO_TIMBERDALE
 	tristate "Support for timberdale Video In/LogiWIN"
-	depends on VIDEO_V4L2 && I2C && DMADEVICES
-	depends on MFD_TIMBERDALE || COMPILE_TEST
-	select DMA_ENGINE
-	select TIMB_DMA
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+	depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST
 	select VIDEO_ADV7180
 	select VIDEOBUF_DMA_CONTIG
 	---help---
@@ -118,6 +116,7 @@ config VIDEO_S3C_CAMIF
 source "drivers/media/platform/soc_camera/Kconfig"
 source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
+source "drivers/media/platform/am437x/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
 
@@ -140,6 +139,7 @@ config VIDEO_CODA
 	depends on HAS_DMA
 	select SRAM
 	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_VMALLOC
 	select V4L2_MEM2MEM_DEV
 	select GENERIC_ALLOCATOR
 	---help---
@@ -213,7 +213,6 @@ config VIDEO_SAMSUNG_EXYNOS_GSC
 config VIDEO_SH_VEU
 	tristate "SuperH VEU mem2mem video processing driver"
 	depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
-	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	help
@@ -223,7 +222,7 @@ config VIDEO_SH_VEU
 config VIDEO_RENESAS_VSP1
 	tristate "Renesas VSP1 Video Processing Engine"
 	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
-	depends on ARCH_SHMOBILE || COMPILE_TEST
+	depends on (ARCH_SHMOBILE && OF) || COMPILE_TEST
 	select VIDEOBUF2_DMA_CONTIG
 	---help---
 	  This is a V4L2 driver for the Renesas VSP1 video processing engine.
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index a49936b8ce8a..3ec154742083 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -46,4 +46,6 @@ obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/
 
 obj-y	+= omap/
 
+obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
+
 ccflags-y += -I$(srctree)/drivers/media/i2c
diff --git a/drivers/media/platform/am437x/Kconfig b/drivers/media/platform/am437x/Kconfig
new file mode 100644
index 000000000000..7b023a76e32e
--- /dev/null
+++ b/drivers/media/platform/am437x/Kconfig
@@ -0,0 +1,11 @@
+config VIDEO_AM437X_VPFE
+	tristate "TI AM437x VPFE video capture driver"
+	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on SOC_AM43XX || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	help
+	   Support for AM437x Video Processing Front End based Video
+	   Capture Driver.
+
+	   To compile this driver as a module, choose M here. The module
+	   will be called am437x-vpfe.
diff --git a/drivers/media/platform/am437x/Makefile b/drivers/media/platform/am437x/Makefile
new file mode 100644
index 000000000000..d11fff16f260
--- /dev/null
+++ b/drivers/media/platform/am437x/Makefile
@@ -0,0 +1,3 @@
+# Makefile for AM437x VPFE driver
+
+obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x-vpfe.o
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
new file mode 100644
index 000000000000..56a5cb0d2152
--- /dev/null
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -0,0 +1,2776 @@
+/*
+ * TI VPFE capture Driver
+ *
+ * Copyright (C) 2013 - 2014 Texas Instruments, Inc.
+ *
+ * Benoit Parrot <bparrot@ti.com>
+ * Lad, Prabhakar <prabhakar.csengg@gmail.com>
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-of.h>
+
+#include "am437x-vpfe.h"
+
+#define VPFE_MODULE_NAME	"vpfe"
+#define VPFE_VERSION		"0.1.0"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-8");
+
+#define vpfe_dbg(level, dev, fmt, arg...)	\
+		v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ##arg)
+#define vpfe_info(dev, fmt, arg...)	\
+		v4l2_info(&dev->v4l2_dev, fmt, ##arg)
+#define vpfe_err(dev, fmt, arg...)	\
+		v4l2_err(&dev->v4l2_dev, fmt, ##arg)
+
+/* standard information */
+struct vpfe_standard {
+	v4l2_std_id std_id;
+	unsigned int width;
+	unsigned int height;
+	struct v4l2_fract pixelaspect;
+	int frame_format;
+};
+
+static const struct vpfe_standard vpfe_standards[] = {
+	{V4L2_STD_525_60, 720, 480, {11, 10}, 1},
+	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
+};
+
+struct bus_format {
+	unsigned int width;
+	unsigned int bpp;
+};
+
+/*
+ * struct vpfe_fmt - VPFE media bus format information
+ * @name: V4L2 format description
+ * @code: V4L2 media bus format code
+ * @shifted: V4L2 media bus format code for the same pixel layout but
+ *	shifted to be 8 bits per pixel. =0 if format is not shiftable.
+ * @pixelformat: V4L2 pixel format FCC identifier
+ * @width: Bits per pixel (when transferred over a bus)
+ * @bpp: Bytes per pixel (when stored in memory)
+ * @supported: Indicates format supported by subdev
+ */
+struct vpfe_fmt {
+	const char *name;
+	u32 fourcc;
+	u32 code;
+	struct bus_format l;
+	struct bus_format s;
+	bool supported;
+	u32 index;
+};
+
+static struct vpfe_fmt formats[] = {
+	{
+		.name		= "YUV 4:2:2 packed, YCbYCr",
+		.fourcc		= V4L2_PIX_FMT_YUYV,
+		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.l.width	= 10,
+		.l.bpp		= 4,
+		.s.width	= 8,
+		.s.bpp		= 2,
+		.supported	= false,
+	}, {
+		.name		= "YUV 4:2:2 packed, CbYCrY",
+		.fourcc		= V4L2_PIX_FMT_UYVY,
+		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.l.width	= 10,
+		.l.bpp		= 4,
+		.s.width	= 8,
+		.s.bpp		= 2,
+		.supported	= false,
+	}, {
+		.name		= "YUV 4:2:2 packed, YCrYCb",
+		.fourcc		= V4L2_PIX_FMT_YVYU,
+		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.l.width	= 10,
+		.l.bpp		= 4,
+		.s.width	= 8,
+		.s.bpp		= 2,
+		.supported	= false,
+	}, {
+		.name		= "YUV 4:2:2 packed, CrYCbY",
+		.fourcc		= V4L2_PIX_FMT_VYUY,
+		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.l.width	= 10,
+		.l.bpp		= 4,
+		.s.width	= 8,
+		.s.bpp		= 2,
+		.supported	= false,
+	}, {
+		.name		= "RAW8 BGGR",
+		.fourcc		= V4L2_PIX_FMT_SBGGR8,
+		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.l.width	= 10,
+		.l.bpp		= 2,
+		.s.width	= 8,
+		.s.bpp		= 1,
+		.supported	= false,
+	}, {
+		.name		= "RAW8 GBRG",
+		.fourcc		= V4L2_PIX_FMT_SGBRG8,
+		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.l.width	= 10,
+		.l.bpp		= 2,
+		.s.width	= 8,
+		.s.bpp		= 1,
+		.supported	= false,
+	}, {
+		.name		= "RAW8 GRBG",
+		.fourcc		= V4L2_PIX_FMT_SGRBG8,
+		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.l.width	= 10,
+		.l.bpp		= 2,
+		.s.width	= 8,
+		.s.bpp		= 1,
+		.supported	= false,
+	}, {
+		.name		= "RAW8 RGGB",
+		.fourcc		= V4L2_PIX_FMT_SRGGB8,
+		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.l.width	= 10,
+		.l.bpp		= 2,
+		.s.width	= 8,
+		.s.bpp		= 1,
+		.supported	= false,
+	}, {
+		.name		= "RGB565 (LE)",
+		.fourcc		= V4L2_PIX_FMT_RGB565,
+		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.l.width	= 10,
+		.l.bpp		= 4,
+		.s.width	= 8,
+		.s.bpp		= 2,
+		.supported	= false,
+	}, {
+		.name		= "RGB565 (BE)",
+		.fourcc		= V4L2_PIX_FMT_RGB565X,
+		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.l.width	= 10,
+		.l.bpp		= 4,
+		.s.width	= 8,
+		.s.bpp		= 2,
+		.supported	= false,
+	},
+};
+
+static int
+__vpfe_get_format(struct vpfe_device *vpfe,
+		  struct v4l2_format *format, unsigned int *bpp);
+
+static struct vpfe_fmt *find_format_by_code(unsigned int code)
+{
+	struct vpfe_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ARRAY_SIZE(formats); k++) {
+		fmt = &formats[k];
+		if (fmt->code == code)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static struct vpfe_fmt *find_format_by_pix(unsigned int pixelformat)
+{
+	struct vpfe_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ARRAY_SIZE(formats); k++) {
+		fmt = &formats[k];
+		if (fmt->fourcc == pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static void
+mbus_to_pix(struct vpfe_device *vpfe,
+	    const struct v4l2_mbus_framefmt *mbus,
+	    struct v4l2_pix_format *pix, unsigned int *bpp)
+{
+	struct vpfe_subdev_info *sdinfo = vpfe->current_subdev;
+	unsigned int bus_width = sdinfo->vpfe_param.bus_width;
+	struct vpfe_fmt *fmt;
+
+	fmt = find_format_by_code(mbus->code);
+	if (WARN_ON(fmt == NULL)) {
+		pr_err("Invalid mbus code set\n");
+		*bpp = 1;
+		return;
+	}
+
+	memset(pix, 0, sizeof(*pix));
+	v4l2_fill_pix_format(pix, mbus);
+	pix->pixelformat = fmt->fourcc;
+	*bpp = (bus_width == 10) ?  fmt->l.bpp : fmt->s.bpp;
+
+	/* pitch should be 32 bytes aligned */
+	pix->bytesperline = ALIGN(pix->width * *bpp, 32);
+	pix->sizeimage = pix->bytesperline * pix->height;
+}
+
+static void pix_to_mbus(struct vpfe_device *vpfe,
+			struct v4l2_pix_format *pix_fmt,
+			struct v4l2_mbus_framefmt *mbus_fmt)
+{
+	struct vpfe_fmt *fmt;
+
+	fmt = find_format_by_pix(pix_fmt->pixelformat);
+	if (!fmt) {
+		/* default to first entry */
+		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
+			pix_fmt->pixelformat);
+		fmt = &formats[0];
+	}
+
+	memset(mbus_fmt, 0, sizeof(*mbus_fmt));
+	v4l2_fill_mbus_format(mbus_fmt, pix_fmt, fmt->code);
+}
+
+/*  Print Four-character-code (FOURCC) */
+static char *print_fourcc(u32 fmt)
+{
+	static char code[5];
+
+	code[0] = (unsigned char)(fmt & 0xff);
+	code[1] = (unsigned char)((fmt >> 8) & 0xff);
+	code[2] = (unsigned char)((fmt >> 16) & 0xff);
+	code[3] = (unsigned char)((fmt >> 24) & 0xff);
+	code[4] = '\0';
+
+	return code;
+}
+
+static int
+cmp_v4l2_format(const struct v4l2_format *lhs, const struct v4l2_format *rhs)
+{
+	return lhs->type == rhs->type &&
+		lhs->fmt.pix.width == rhs->fmt.pix.width &&
+		lhs->fmt.pix.height == rhs->fmt.pix.height &&
+		lhs->fmt.pix.pixelformat == rhs->fmt.pix.pixelformat &&
+		lhs->fmt.pix.field == rhs->fmt.pix.field &&
+		lhs->fmt.pix.colorspace == rhs->fmt.pix.colorspace &&
+		lhs->fmt.pix.ycbcr_enc == rhs->fmt.pix.ycbcr_enc &&
+		lhs->fmt.pix.quantization == rhs->fmt.pix.quantization;
+}
+
+static inline u32 vpfe_reg_read(struct vpfe_ccdc *ccdc, u32 offset)
+{
+	return ioread32(ccdc->ccdc_cfg.base_addr + offset);
+}
+
+static inline void vpfe_reg_write(struct vpfe_ccdc *ccdc, u32 val, u32 offset)
+{
+	iowrite32(val, ccdc->ccdc_cfg.base_addr + offset);
+}
+
+static inline struct vpfe_device *to_vpfe(struct vpfe_ccdc *ccdc)
+{
+	return container_of(ccdc, struct vpfe_device, ccdc);
+}
+
+static inline struct vpfe_cap_buffer *to_vpfe_buffer(struct vb2_buffer *vb)
+{
+	return container_of(vb, struct vpfe_cap_buffer, vb);
+}
+
+static inline void vpfe_pcr_enable(struct vpfe_ccdc *ccdc, int flag)
+{
+	vpfe_reg_write(ccdc, !!flag, VPFE_PCR);
+}
+
+static void vpfe_config_enable(struct vpfe_ccdc *ccdc, int flag)
+{
+	unsigned int cfg;
+
+	if (!flag) {
+		cfg = vpfe_reg_read(ccdc, VPFE_CONFIG);
+		cfg &= ~(VPFE_CONFIG_EN_ENABLE << VPFE_CONFIG_EN_SHIFT);
+	} else {
+		cfg = VPFE_CONFIG_EN_ENABLE << VPFE_CONFIG_EN_SHIFT;
+	}
+
+	vpfe_reg_write(ccdc, cfg, VPFE_CONFIG);
+}
+
+static void vpfe_ccdc_setwin(struct vpfe_ccdc *ccdc,
+			     struct v4l2_rect *image_win,
+			     enum ccdc_frmfmt frm_fmt,
+			     int bpp)
+{
+	int horz_start, horz_nr_pixels;
+	int vert_start, vert_nr_lines;
+	int val, mid_img;
+
+	/*
+	 * ppc - per pixel count. indicates how many pixels per cell
+	 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
+	 * raw capture this is 1
+	 */
+	horz_start = image_win->left * bpp;
+	horz_nr_pixels = (image_win->width * bpp) - 1;
+	vpfe_reg_write(ccdc, (horz_start << VPFE_HORZ_INFO_SPH_SHIFT) |
+				horz_nr_pixels, VPFE_HORZ_INFO);
+
+	vert_start = image_win->top;
+
+	if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		vert_nr_lines = (image_win->height >> 1) - 1;
+		vert_start >>= 1;
+		/* Since first line doesn't have any data */
+		vert_start += 1;
+		/* configure VDINT0 */
+		val = (vert_start << VPFE_VDINT_VDINT0_SHIFT);
+	} else {
+		/* Since first line doesn't have any data */
+		vert_start += 1;
+		vert_nr_lines = image_win->height - 1;
+		/*
+		 * configure VDINT0 and VDINT1. VDINT1 will be at half
+		 * of image height
+		 */
+		mid_img = vert_start + (image_win->height / 2);
+		val = (vert_start << VPFE_VDINT_VDINT0_SHIFT) |
+				(mid_img & VPFE_VDINT_VDINT1_MASK);
+	}
+
+	vpfe_reg_write(ccdc, val, VPFE_VDINT);
+
+	vpfe_reg_write(ccdc, (vert_start << VPFE_VERT_START_SLV0_SHIFT) |
+				vert_start, VPFE_VERT_START);
+	vpfe_reg_write(ccdc, vert_nr_lines, VPFE_VERT_LINES);
+}
+
+static void vpfe_reg_dump(struct vpfe_ccdc *ccdc)
+{
+	struct vpfe_device *vpfe = to_vpfe(ccdc);
+
+	vpfe_dbg(3, vpfe, "ALAW: 0x%x\n", vpfe_reg_read(ccdc, VPFE_ALAW));
+	vpfe_dbg(3, vpfe, "CLAMP: 0x%x\n", vpfe_reg_read(ccdc, VPFE_CLAMP));
+	vpfe_dbg(3, vpfe, "DCSUB: 0x%x\n", vpfe_reg_read(ccdc, VPFE_DCSUB));
+	vpfe_dbg(3, vpfe, "BLKCMP: 0x%x\n", vpfe_reg_read(ccdc, VPFE_BLKCMP));
+	vpfe_dbg(3, vpfe, "COLPTN: 0x%x\n", vpfe_reg_read(ccdc, VPFE_COLPTN));
+	vpfe_dbg(3, vpfe, "SDOFST: 0x%x\n", vpfe_reg_read(ccdc, VPFE_SDOFST));
+	vpfe_dbg(3, vpfe, "SYN_MODE: 0x%x\n",
+		 vpfe_reg_read(ccdc, VPFE_SYNMODE));
+	vpfe_dbg(3, vpfe, "HSIZE_OFF: 0x%x\n",
+		 vpfe_reg_read(ccdc, VPFE_HSIZE_OFF));
+	vpfe_dbg(3, vpfe, "HORZ_INFO: 0x%x\n",
+		 vpfe_reg_read(ccdc, VPFE_HORZ_INFO));
+	vpfe_dbg(3, vpfe, "VERT_START: 0x%x\n",
+		 vpfe_reg_read(ccdc, VPFE_VERT_START));
+	vpfe_dbg(3, vpfe, "VERT_LINES: 0x%x\n",
+		 vpfe_reg_read(ccdc, VPFE_VERT_LINES));
+}
+
+static int
+vpfe_ccdc_validate_param(struct vpfe_ccdc *ccdc,
+			 struct vpfe_ccdc_config_params_raw *ccdcparam)
+{
+	struct vpfe_device *vpfe = to_vpfe(ccdc);
+	u8 max_gamma, max_data;
+
+	if (!ccdcparam->alaw.enable)
+		return 0;
+
+	max_gamma = ccdc_gamma_width_max_bit(ccdcparam->alaw.gamma_wd);
+	max_data = ccdc_data_size_max_bit(ccdcparam->data_sz);
+
+	if (ccdcparam->alaw.gamma_wd > VPFE_CCDC_GAMMA_BITS_09_0 ||
+	    ccdcparam->alaw.gamma_wd < VPFE_CCDC_GAMMA_BITS_15_6 ||
+	    max_gamma > max_data) {
+		vpfe_dbg(1, vpfe, "Invalid data line select\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void
+vpfe_ccdc_update_raw_params(struct vpfe_ccdc *ccdc,
+			    struct vpfe_ccdc_config_params_raw *raw_params)
+{
+	struct vpfe_ccdc_config_params_raw *config_params =
+				&ccdc->ccdc_cfg.bayer.config_params;
+
+	config_params = raw_params;
+}
+
+/*
+ * vpfe_ccdc_restore_defaults()
+ * This function will write defaults to all CCDC registers
+ */
+static void vpfe_ccdc_restore_defaults(struct vpfe_ccdc *ccdc)
+{
+	int i;
+
+	/* Disable CCDC */
+	vpfe_pcr_enable(ccdc, 0);
+
+	/* set all registers to default value */
+	for (i = 4; i <= 0x94; i += 4)
+		vpfe_reg_write(ccdc, 0,  i);
+
+	vpfe_reg_write(ccdc, VPFE_NO_CULLING, VPFE_CULLING);
+	vpfe_reg_write(ccdc, VPFE_CCDC_GAMMA_BITS_11_2, VPFE_ALAW);
+}
+
+static int vpfe_ccdc_close(struct vpfe_ccdc *ccdc, struct device *dev)
+{
+	int dma_cntl, i, pcr;
+
+	/* If the CCDC module is still busy wait for it to be done */
+	for (i = 0; i < 10; i++) {
+		usleep_range(5000, 6000);
+		pcr = vpfe_reg_read(ccdc, VPFE_PCR);
+		if (!pcr)
+			break;
+
+		/* make sure it it is disabled */
+		vpfe_pcr_enable(ccdc, 0);
+	}
+
+	/* Disable CCDC by resetting all register to default POR values */
+	vpfe_ccdc_restore_defaults(ccdc);
+
+	/* if DMA_CNTL overflow bit is set. Clear it
+	 *  It appears to take a while for this to become quiescent ~20ms
+	 */
+	for (i = 0; i < 10; i++) {
+		dma_cntl = vpfe_reg_read(ccdc, VPFE_DMA_CNTL);
+		if (!(dma_cntl & VPFE_DMA_CNTL_OVERFLOW))
+			break;
+
+		/* Clear the overflow bit */
+		vpfe_reg_write(ccdc, dma_cntl, VPFE_DMA_CNTL);
+		usleep_range(5000, 6000);
+	}
+
+	/* Disabled the module at the CONFIG level */
+	vpfe_config_enable(ccdc, 0);
+
+	pm_runtime_put_sync(dev);
+
+	return 0;
+}
+
+static int vpfe_ccdc_set_params(struct vpfe_ccdc *ccdc, void __user *params)
+{
+	struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc);
+	struct vpfe_ccdc_config_params_raw raw_params;
+	int x;
+
+	if (ccdc->ccdc_cfg.if_type != VPFE_RAW_BAYER)
+		return -EINVAL;
+
+	x = copy_from_user(&raw_params, params, sizeof(raw_params));
+	if (x) {
+		vpfe_dbg(1, vpfe,
+			"vpfe_ccdc_set_params: error in copying ccdc params, %d\n",
+			x);
+		return -EFAULT;
+	}
+
+	if (!vpfe_ccdc_validate_param(ccdc, &raw_params)) {
+		vpfe_ccdc_update_raw_params(ccdc, &raw_params);
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * vpfe_ccdc_config_ycbcr()
+ * This function will configure CCDC for YCbCr video capture
+ */
+static void vpfe_ccdc_config_ycbcr(struct vpfe_ccdc *ccdc)
+{
+	struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc);
+	struct ccdc_params_ycbcr *params = &ccdc->ccdc_cfg.ycbcr;
+	u32 syn_mode;
+
+	vpfe_dbg(3, vpfe, "vpfe_ccdc_config_ycbcr:\n");
+	/*
+	 * first restore the CCDC registers to default values
+	 * This is important since we assume default values to be set in
+	 * a lot of registers that we didn't touch
+	 */
+	vpfe_ccdc_restore_defaults(ccdc);
+
+	/*
+	 * configure pixel format, frame format, configure video frame
+	 * format, enable output to SDRAM, enable internal timing generator
+	 * and 8bit pack mode
+	 */
+	syn_mode = (((params->pix_fmt & VPFE_SYN_MODE_INPMOD_MASK) <<
+		    VPFE_SYN_MODE_INPMOD_SHIFT) |
+		    ((params->frm_fmt & VPFE_SYN_FLDMODE_MASK) <<
+		    VPFE_SYN_FLDMODE_SHIFT) | VPFE_VDHDEN_ENABLE |
+		    VPFE_WEN_ENABLE | VPFE_DATA_PACK_ENABLE);
+
+	/* setup BT.656 sync mode */
+	if (params->bt656_enable) {
+		vpfe_reg_write(ccdc, VPFE_REC656IF_BT656_EN, VPFE_REC656IF);
+
+		/*
+		 * configure the FID, VD, HD pin polarity,
+		 * fld,hd pol positive, vd negative, 8-bit data
+		 */
+		syn_mode |= VPFE_SYN_MODE_VD_POL_NEGATIVE;
+		if (ccdc->ccdc_cfg.if_type == VPFE_BT656_10BIT)
+			syn_mode |= VPFE_SYN_MODE_10BITS;
+		else
+			syn_mode |= VPFE_SYN_MODE_8BITS;
+	} else {
+		/* y/c external sync mode */
+		syn_mode |= (((params->fid_pol & VPFE_FID_POL_MASK) <<
+			     VPFE_FID_POL_SHIFT) |
+			     ((params->hd_pol & VPFE_HD_POL_MASK) <<
+			     VPFE_HD_POL_SHIFT) |
+			     ((params->vd_pol & VPFE_VD_POL_MASK) <<
+			     VPFE_VD_POL_SHIFT));
+	}
+	vpfe_reg_write(ccdc, syn_mode, VPFE_SYNMODE);
+
+	/* configure video window */
+	vpfe_ccdc_setwin(ccdc, &params->win,
+			 params->frm_fmt, params->bytesperpixel);
+
+	/*
+	 * configure the order of y cb cr in SDRAM, and disable latch
+	 * internal register on vsync
+	 */
+	if (ccdc->ccdc_cfg.if_type == VPFE_BT656_10BIT)
+		vpfe_reg_write(ccdc,
+			       (params->pix_order << VPFE_CCDCFG_Y8POS_SHIFT) |
+			       VPFE_LATCH_ON_VSYNC_DISABLE |
+			       VPFE_CCDCFG_BW656_10BIT, VPFE_CCDCFG);
+	else
+		vpfe_reg_write(ccdc,
+			       (params->pix_order << VPFE_CCDCFG_Y8POS_SHIFT) |
+			       VPFE_LATCH_ON_VSYNC_DISABLE, VPFE_CCDCFG);
+
+	/*
+	 * configure the horizontal line offset. This should be a
+	 * on 32 byte boundary. So clear LSB 5 bits
+	 */
+	vpfe_reg_write(ccdc, params->bytesperline, VPFE_HSIZE_OFF);
+
+	/* configure the memory line offset */
+	if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
+		/* two fields are interleaved in memory */
+		vpfe_reg_write(ccdc, VPFE_SDOFST_FIELD_INTERLEAVED,
+			       VPFE_SDOFST);
+}
+
+static void
+vpfe_ccdc_config_black_clamp(struct vpfe_ccdc *ccdc,
+			     struct vpfe_ccdc_black_clamp *bclamp)
+{
+	u32 val;
+
+	if (!bclamp->enable) {
+		/* configure DCSub */
+		val = (bclamp->dc_sub) & VPFE_BLK_DC_SUB_MASK;
+		vpfe_reg_write(ccdc, val, VPFE_DCSUB);
+		vpfe_reg_write(ccdc, VPFE_CLAMP_DEFAULT_VAL, VPFE_CLAMP);
+		return;
+	}
+	/*
+	 * Configure gain,  Start pixel, No of line to be avg,
+	 * No of pixel/line to be avg, & Enable the Black clamping
+	 */
+	val = ((bclamp->sgain & VPFE_BLK_SGAIN_MASK) |
+	       ((bclamp->start_pixel & VPFE_BLK_ST_PXL_MASK) <<
+		VPFE_BLK_ST_PXL_SHIFT) |
+	       ((bclamp->sample_ln & VPFE_BLK_SAMPLE_LINE_MASK) <<
+		VPFE_BLK_SAMPLE_LINE_SHIFT) |
+	       ((bclamp->sample_pixel & VPFE_BLK_SAMPLE_LN_MASK) <<
+		VPFE_BLK_SAMPLE_LN_SHIFT) | VPFE_BLK_CLAMP_ENABLE);
+	vpfe_reg_write(ccdc, val, VPFE_CLAMP);
+	/* If Black clamping is enable then make dcsub 0 */
+	vpfe_reg_write(ccdc, VPFE_DCSUB_DEFAULT_VAL, VPFE_DCSUB);
+}
+
+static void
+vpfe_ccdc_config_black_compense(struct vpfe_ccdc *ccdc,
+				struct vpfe_ccdc_black_compensation *bcomp)
+{
+	u32 val;
+
+	val = ((bcomp->b & VPFE_BLK_COMP_MASK) |
+	      ((bcomp->gb & VPFE_BLK_COMP_MASK) <<
+	       VPFE_BLK_COMP_GB_COMP_SHIFT) |
+	      ((bcomp->gr & VPFE_BLK_COMP_MASK) <<
+	       VPFE_BLK_COMP_GR_COMP_SHIFT) |
+	      ((bcomp->r & VPFE_BLK_COMP_MASK) <<
+	       VPFE_BLK_COMP_R_COMP_SHIFT));
+	vpfe_reg_write(ccdc, val, VPFE_BLKCMP);
+}
+
+/*
+ * vpfe_ccdc_config_raw()
+ * This function will configure CCDC for Raw capture mode
+ */
+static void vpfe_ccdc_config_raw(struct vpfe_ccdc *ccdc)
+{
+	struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc);
+	struct vpfe_ccdc_config_params_raw *config_params =
+				&ccdc->ccdc_cfg.bayer.config_params;
+	struct ccdc_params_raw *params = &ccdc->ccdc_cfg.bayer;
+	unsigned int syn_mode;
+	unsigned int val;
+
+	vpfe_dbg(3, vpfe, "vpfe_ccdc_config_raw:\n");
+
+	/* Reset CCDC */
+	vpfe_ccdc_restore_defaults(ccdc);
+
+	/* Disable latching function registers on VSYNC  */
+	vpfe_reg_write(ccdc, VPFE_LATCH_ON_VSYNC_DISABLE, VPFE_CCDCFG);
+
+	/*
+	 * Configure the vertical sync polarity(SYN_MODE.VDPOL),
+	 * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity
+	 * (SYN_MODE.FLDPOL), frame format(progressive or interlace),
+	 * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output
+	 * SDRAM, enable internal timing generator
+	 */
+	syn_mode = (((params->vd_pol & VPFE_VD_POL_MASK) << VPFE_VD_POL_SHIFT) |
+		   ((params->hd_pol & VPFE_HD_POL_MASK) << VPFE_HD_POL_SHIFT) |
+		   ((params->fid_pol & VPFE_FID_POL_MASK) <<
+		   VPFE_FID_POL_SHIFT) | ((params->frm_fmt &
+		   VPFE_FRM_FMT_MASK) << VPFE_FRM_FMT_SHIFT) |
+		   ((config_params->data_sz & VPFE_DATA_SZ_MASK) <<
+		   VPFE_DATA_SZ_SHIFT) | ((params->pix_fmt &
+		   VPFE_PIX_FMT_MASK) << VPFE_PIX_FMT_SHIFT) |
+		   VPFE_WEN_ENABLE | VPFE_VDHDEN_ENABLE);
+
+	/* Enable and configure aLaw register if needed */
+	if (config_params->alaw.enable) {
+		val = ((config_params->alaw.gamma_wd &
+		      VPFE_ALAW_GAMMA_WD_MASK) | VPFE_ALAW_ENABLE);
+		vpfe_reg_write(ccdc, val, VPFE_ALAW);
+		vpfe_dbg(3, vpfe, "\nWriting 0x%x to ALAW...\n", val);
+	}
+
+	/* Configure video window */
+	vpfe_ccdc_setwin(ccdc, &params->win, params->frm_fmt,
+			 params->bytesperpixel);
+
+	/* Configure Black Clamp */
+	vpfe_ccdc_config_black_clamp(ccdc, &config_params->blk_clamp);
+
+	/* Configure Black level compensation */
+	vpfe_ccdc_config_black_compense(ccdc, &config_params->blk_comp);
+
+	/* If data size is 8 bit then pack the data */
+	if ((config_params->data_sz == VPFE_CCDC_DATA_8BITS) ||
+	    config_params->alaw.enable)
+		syn_mode |= VPFE_DATA_PACK_ENABLE;
+
+	/*
+	 * Configure Horizontal offset register. If pack 8 is enabled then
+	 * 1 pixel will take 1 byte
+	 */
+	vpfe_reg_write(ccdc, params->bytesperline, VPFE_HSIZE_OFF);
+
+	vpfe_dbg(3, vpfe, "Writing %d (%x) to HSIZE_OFF\n",
+		params->bytesperline, params->bytesperline);
+
+	/* Set value for SDOFST */
+	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		if (params->image_invert_enable) {
+			/* For interlace inverse mode */
+			vpfe_reg_write(ccdc, VPFE_INTERLACED_IMAGE_INVERT,
+				   VPFE_SDOFST);
+		} else {
+			/* For interlace non inverse mode */
+			vpfe_reg_write(ccdc, VPFE_INTERLACED_NO_IMAGE_INVERT,
+				   VPFE_SDOFST);
+		}
+	} else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
+		vpfe_reg_write(ccdc, VPFE_PROGRESSIVE_NO_IMAGE_INVERT,
+			   VPFE_SDOFST);
+	}
+
+	vpfe_reg_write(ccdc, syn_mode, VPFE_SYNMODE);
+
+	vpfe_reg_dump(ccdc);
+}
+
+static inline int
+vpfe_ccdc_set_buftype(struct vpfe_ccdc *ccdc,
+		      enum ccdc_buftype buf_type)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		ccdc->ccdc_cfg.bayer.buf_type = buf_type;
+	else
+		ccdc->ccdc_cfg.ycbcr.buf_type = buf_type;
+
+	return 0;
+}
+
+static inline enum ccdc_buftype vpfe_ccdc_get_buftype(struct vpfe_ccdc *ccdc)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		return ccdc->ccdc_cfg.bayer.buf_type;
+
+	return ccdc->ccdc_cfg.ycbcr.buf_type;
+}
+
+static int vpfe_ccdc_set_pixel_format(struct vpfe_ccdc *ccdc, u32 pixfmt)
+{
+	struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc);
+
+	vpfe_dbg(1, vpfe, "vpfe_ccdc_set_pixel_format: if_type: %d, pixfmt:%s\n",
+		 ccdc->ccdc_cfg.if_type, print_fourcc(pixfmt));
+
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		ccdc->ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
+		/*
+		 * Need to clear it in case it was left on
+		 * after the last capture.
+		 */
+		ccdc->ccdc_cfg.bayer.config_params.alaw.enable = 0;
+
+		switch (pixfmt) {
+		case V4L2_PIX_FMT_SBGGR8:
+			ccdc->ccdc_cfg.bayer.config_params.alaw.enable = 1;
+			break;
+
+		case V4L2_PIX_FMT_YUYV:
+		case V4L2_PIX_FMT_UYVY:
+		case V4L2_PIX_FMT_YUV420:
+		case V4L2_PIX_FMT_NV12:
+		case V4L2_PIX_FMT_RGB565X:
+			break;
+
+		case V4L2_PIX_FMT_SBGGR16:
+		default:
+			return -EINVAL;
+		}
+	} else {
+		switch (pixfmt) {
+		case V4L2_PIX_FMT_YUYV:
+			ccdc->ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
+			break;
+
+		case V4L2_PIX_FMT_UYVY:
+			ccdc->ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static u32 vpfe_ccdc_get_pixel_format(struct vpfe_ccdc *ccdc)
+{
+	u32 pixfmt;
+
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		pixfmt = V4L2_PIX_FMT_YUYV;
+	} else {
+		if (ccdc->ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
+			pixfmt = V4L2_PIX_FMT_YUYV;
+		else
+			pixfmt = V4L2_PIX_FMT_UYVY;
+	}
+
+	return pixfmt;
+}
+
+static int
+vpfe_ccdc_set_image_window(struct vpfe_ccdc *ccdc,
+			   struct v4l2_rect *win, unsigned int bpp)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) {
+		ccdc->ccdc_cfg.bayer.win = *win;
+		ccdc->ccdc_cfg.bayer.bytesperpixel = bpp;
+		ccdc->ccdc_cfg.bayer.bytesperline = ALIGN(win->width * bpp, 32);
+	} else {
+		ccdc->ccdc_cfg.ycbcr.win = *win;
+		ccdc->ccdc_cfg.ycbcr.bytesperpixel = bpp;
+		ccdc->ccdc_cfg.ycbcr.bytesperline = ALIGN(win->width * bpp, 32);
+	}
+
+	return 0;
+}
+
+static inline void
+vpfe_ccdc_get_image_window(struct vpfe_ccdc *ccdc,
+			   struct v4l2_rect *win)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		*win = ccdc->ccdc_cfg.bayer.win;
+	else
+		*win = ccdc->ccdc_cfg.ycbcr.win;
+}
+
+static inline unsigned int vpfe_ccdc_get_line_length(struct vpfe_ccdc *ccdc)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		return ccdc->ccdc_cfg.bayer.bytesperline;
+
+	return ccdc->ccdc_cfg.ycbcr.bytesperline;
+}
+
+static inline int
+vpfe_ccdc_set_frame_format(struct vpfe_ccdc *ccdc,
+			   enum ccdc_frmfmt frm_fmt)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		ccdc->ccdc_cfg.bayer.frm_fmt = frm_fmt;
+	else
+		ccdc->ccdc_cfg.ycbcr.frm_fmt = frm_fmt;
+
+	return 0;
+}
+
+static inline enum ccdc_frmfmt
+vpfe_ccdc_get_frame_format(struct vpfe_ccdc *ccdc)
+{
+	if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		return ccdc->ccdc_cfg.bayer.frm_fmt;
+
+	return ccdc->ccdc_cfg.ycbcr.frm_fmt;
+}
+
+static inline int vpfe_ccdc_getfid(struct vpfe_ccdc *ccdc)
+{
+	return (vpfe_reg_read(ccdc, VPFE_SYNMODE) >> 15) & 1;
+}
+
+static inline void vpfe_set_sdr_addr(struct vpfe_ccdc *ccdc, unsigned long addr)
+{
+	vpfe_reg_write(ccdc, addr & 0xffffffe0, VPFE_SDR_ADDR);
+}
+
+static int vpfe_ccdc_set_hw_if_params(struct vpfe_ccdc *ccdc,
+				      struct vpfe_hw_if_param *params)
+{
+	struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc);
+
+	ccdc->ccdc_cfg.if_type = params->if_type;
+
+	switch (params->if_type) {
+	case VPFE_BT656:
+	case VPFE_YCBCR_SYNC_16:
+	case VPFE_YCBCR_SYNC_8:
+	case VPFE_BT656_10BIT:
+		ccdc->ccdc_cfg.ycbcr.vd_pol = params->vdpol;
+		ccdc->ccdc_cfg.ycbcr.hd_pol = params->hdpol;
+		break;
+
+	case VPFE_RAW_BAYER:
+		ccdc->ccdc_cfg.bayer.vd_pol = params->vdpol;
+		ccdc->ccdc_cfg.bayer.hd_pol = params->hdpol;
+		if (params->bus_width == 10)
+			ccdc->ccdc_cfg.bayer.config_params.data_sz =
+				VPFE_CCDC_DATA_10BITS;
+		else
+			ccdc->ccdc_cfg.bayer.config_params.data_sz =
+				VPFE_CCDC_DATA_8BITS;
+		vpfe_dbg(1, vpfe, "params.bus_width: %d\n",
+			params->bus_width);
+		vpfe_dbg(1, vpfe, "config_params.data_sz: %d\n",
+			ccdc->ccdc_cfg.bayer.config_params.data_sz);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vpfe_clear_intr(struct vpfe_ccdc *ccdc, int vdint)
+{
+	unsigned int vpfe_int_status;
+
+	vpfe_int_status = vpfe_reg_read(ccdc, VPFE_IRQ_STS);
+
+	switch (vdint) {
+	/* VD0 interrupt */
+	case VPFE_VDINT0:
+		vpfe_int_status &= ~VPFE_VDINT0;
+		vpfe_int_status |= VPFE_VDINT0;
+		break;
+
+	/* VD1 interrupt */
+	case VPFE_VDINT1:
+		vpfe_int_status &= ~VPFE_VDINT1;
+		vpfe_int_status |= VPFE_VDINT1;
+		break;
+
+	/* VD2 interrupt */
+	case VPFE_VDINT2:
+		vpfe_int_status &= ~VPFE_VDINT2;
+		vpfe_int_status |= VPFE_VDINT2;
+		break;
+
+	/* Clear all interrupts */
+	default:
+		vpfe_int_status &= ~(VPFE_VDINT0 |
+				VPFE_VDINT1 |
+				VPFE_VDINT2);
+		vpfe_int_status |= (VPFE_VDINT0 |
+				VPFE_VDINT1 |
+				VPFE_VDINT2);
+		break;
+	}
+	/* Clear specific VDINT from the status register */
+	vpfe_reg_write(ccdc, vpfe_int_status, VPFE_IRQ_STS);
+
+	vpfe_int_status = vpfe_reg_read(ccdc, VPFE_IRQ_STS);
+
+	/* Acknowledge that we are done with all interrupts */
+	vpfe_reg_write(ccdc, 1, VPFE_IRQ_EOI);
+}
+
+static void vpfe_ccdc_config_defaults(struct vpfe_ccdc *ccdc)
+{
+	ccdc->ccdc_cfg.if_type = VPFE_RAW_BAYER;
+
+	ccdc->ccdc_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT;
+	ccdc->ccdc_cfg.ycbcr.frm_fmt = CCDC_FRMFMT_INTERLACED;
+	ccdc->ccdc_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE;
+	ccdc->ccdc_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE;
+	ccdc->ccdc_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE;
+	ccdc->ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
+	ccdc->ccdc_cfg.ycbcr.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED;
+
+	ccdc->ccdc_cfg.ycbcr.win.left = 0;
+	ccdc->ccdc_cfg.ycbcr.win.top = 0;
+	ccdc->ccdc_cfg.ycbcr.win.width = 720;
+	ccdc->ccdc_cfg.ycbcr.win.height = 576;
+	ccdc->ccdc_cfg.ycbcr.bt656_enable = 1;
+
+	ccdc->ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
+	ccdc->ccdc_cfg.bayer.frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
+	ccdc->ccdc_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE;
+	ccdc->ccdc_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE;
+	ccdc->ccdc_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE;
+
+	ccdc->ccdc_cfg.bayer.win.left = 0;
+	ccdc->ccdc_cfg.bayer.win.top = 0;
+	ccdc->ccdc_cfg.bayer.win.width = 800;
+	ccdc->ccdc_cfg.bayer.win.height = 600;
+	ccdc->ccdc_cfg.bayer.config_params.data_sz = VPFE_CCDC_DATA_8BITS;
+	ccdc->ccdc_cfg.bayer.config_params.alaw.gamma_wd =
+						VPFE_CCDC_GAMMA_BITS_09_0;
+}
+
+/*
+ * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings
+ */
+static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe,
+				      struct v4l2_format *f)
+{
+	struct v4l2_rect image_win;
+	enum ccdc_buftype buf_type;
+	enum ccdc_frmfmt frm_fmt;
+
+	memset(f, 0, sizeof(*f));
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	vpfe_ccdc_get_image_window(&vpfe->ccdc, &image_win);
+	f->fmt.pix.width = image_win.width;
+	f->fmt.pix.height = image_win.height;
+	f->fmt.pix.bytesperline = vpfe_ccdc_get_line_length(&vpfe->ccdc);
+	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+				f->fmt.pix.height;
+	buf_type = vpfe_ccdc_get_buftype(&vpfe->ccdc);
+	f->fmt.pix.pixelformat = vpfe_ccdc_get_pixel_format(&vpfe->ccdc);
+	frm_fmt = vpfe_ccdc_get_frame_format(&vpfe->ccdc);
+
+	if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+	} else if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
+			f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+		 } else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED) {
+			f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
+		} else {
+			vpfe_err(vpfe, "Invalid buf_type\n");
+			return -EINVAL;
+		}
+	} else {
+		vpfe_err(vpfe, "Invalid frm_fmt\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe)
+{
+	enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
+	int ret;
+
+	vpfe_dbg(2, vpfe, "vpfe_config_ccdc_image_format\n");
+
+	vpfe_dbg(1, vpfe, "pixelformat: %s\n",
+		print_fourcc(vpfe->fmt.fmt.pix.pixelformat));
+
+	if (vpfe_ccdc_set_pixel_format(&vpfe->ccdc,
+			vpfe->fmt.fmt.pix.pixelformat) < 0) {
+		vpfe_err(vpfe, "couldn't set pix format in ccdc\n");
+		return -EINVAL;
+	}
+
+	/* configure the image window */
+	vpfe_ccdc_set_image_window(&vpfe->ccdc, &vpfe->crop, vpfe->bpp);
+
+	switch (vpfe->fmt.fmt.pix.field) {
+	case V4L2_FIELD_INTERLACED:
+		/* do nothing, since it is default */
+		ret = vpfe_ccdc_set_buftype(
+				&vpfe->ccdc,
+				CCDC_BUFTYPE_FLD_INTERLEAVED);
+		break;
+
+	case V4L2_FIELD_NONE:
+		frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
+		/* buffer type only applicable for interlaced scan */
+		break;
+
+	case V4L2_FIELD_SEQ_TB:
+		ret = vpfe_ccdc_set_buftype(
+				&vpfe->ccdc,
+				CCDC_BUFTYPE_FLD_SEPARATED);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (ret)
+		return ret;
+
+	return vpfe_ccdc_set_frame_format(&vpfe->ccdc, frm_fmt);
+}
+
+/*
+ * vpfe_config_image_format()
+ * For a given standard, this functions sets up the default
+ * pix format & crop values in the vpfe device and ccdc.  It first
+ * starts with defaults based values from the standard table.
+ * It then checks if sub device support g_mbus_fmt and then override the
+ * values based on that.Sets crop values to match with scan resolution
+ * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
+ * values in ccdc
+ */
+static int vpfe_config_image_format(struct vpfe_device *vpfe,
+				    v4l2_std_id std_id)
+{
+	struct v4l2_pix_format *pix = &vpfe->fmt.fmt.pix;
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
+		if (vpfe_standards[i].std_id & std_id) {
+			vpfe->std_info.active_pixels =
+					vpfe_standards[i].width;
+			vpfe->std_info.active_lines =
+					vpfe_standards[i].height;
+			vpfe->std_info.frame_format =
+					vpfe_standards[i].frame_format;
+			vpfe->std_index = i;
+
+			break;
+		}
+	}
+
+	if (i ==  ARRAY_SIZE(vpfe_standards)) {
+		vpfe_err(vpfe, "standard not supported\n");
+		return -EINVAL;
+	}
+
+	vpfe->crop.top = vpfe->crop.left = 0;
+	vpfe->crop.width = vpfe->std_info.active_pixels;
+	vpfe->crop.height = vpfe->std_info.active_lines;
+	pix->width = vpfe->crop.width;
+	pix->height = vpfe->crop.height;
+	pix->pixelformat = V4L2_PIX_FMT_YUYV;
+
+	/* first field and frame format based on standard frame format */
+	if (vpfe->std_info.frame_format)
+		pix->field = V4L2_FIELD_INTERLACED;
+	else
+		pix->field = V4L2_FIELD_NONE;
+
+	ret = __vpfe_get_format(vpfe, &vpfe->fmt, &vpfe->bpp);
+	if (ret)
+		return ret;
+
+	/* Update the crop window based on found values */
+	vpfe->crop.width = pix->width;
+	vpfe->crop.height = pix->height;
+
+	return vpfe_config_ccdc_image_format(vpfe);
+}
+
+static int vpfe_initialize_device(struct vpfe_device *vpfe)
+{
+	struct vpfe_subdev_info *sdinfo;
+	int ret;
+
+	sdinfo = &vpfe->cfg->sub_devs[0];
+	sdinfo->sd = vpfe->sd[0];
+	vpfe->current_input = 0;
+	vpfe->std_index = 0;
+	/* Configure the default format information */
+	ret = vpfe_config_image_format(vpfe,
+				       vpfe_standards[vpfe->std_index].std_id);
+	if (ret)
+		return ret;
+
+	pm_runtime_get_sync(vpfe->pdev);
+
+	vpfe_config_enable(&vpfe->ccdc, 1);
+
+	vpfe_ccdc_restore_defaults(&vpfe->ccdc);
+
+	/* Clear all VPFE interrupts */
+	vpfe_clear_intr(&vpfe->ccdc, -1);
+
+	return ret;
+}
+
+/*
+ * vpfe_release : This function is based on the vb2_fop_release
+ * helper function.
+ * It has been augmented to handle module power management,
+ * by disabling/enabling h/w module fcntl clock when necessary.
+ */
+static int vpfe_release(struct file *file)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&vpfe->lock);
+
+	if (v4l2_fh_is_singular_file(file))
+		vpfe_ccdc_close(&vpfe->ccdc, vpfe->pdev);
+	ret = _vb2_fop_release(file, NULL);
+
+	mutex_unlock(&vpfe->lock);
+
+	return ret;
+}
+
+/*
+ * vpfe_open : This function is based on the v4l2_fh_open helper function.
+ * It has been augmented to handle module power management,
+ * by disabling/enabling h/w module fcntl clock when necessary.
+ */
+static int vpfe_open(struct file *file)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&vpfe->lock);
+
+	ret = v4l2_fh_open(file);
+	if (ret) {
+		vpfe_err(vpfe, "v4l2_fh_open failed\n");
+		goto unlock;
+	}
+
+	if (!v4l2_fh_is_singular_file(file))
+		goto unlock;
+
+	if (vpfe_initialize_device(vpfe)) {
+		v4l2_fh_release(file);
+		ret = -ENODEV;
+	}
+
+unlock:
+	mutex_unlock(&vpfe->lock);
+	return ret;
+}
+
+/**
+ * vpfe_schedule_next_buffer: set next buffer address for capture
+ * @vpfe : ptr to vpfe device
+ *
+ * This function will get next buffer from the dma queue and
+ * set the buffer address in the vpfe register for capture.
+ * the buffer is marked active
+ *
+ * Assumes caller is holding vpfe->dma_queue_lock already
+ */
+static inline void vpfe_schedule_next_buffer(struct vpfe_device *vpfe)
+{
+	vpfe->next_frm = list_entry(vpfe->dma_queue.next,
+				    struct vpfe_cap_buffer, list);
+	list_del(&vpfe->next_frm->list);
+
+	vpfe_set_sdr_addr(&vpfe->ccdc,
+		       vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0));
+}
+
+static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe)
+{
+	unsigned long addr;
+
+	addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0) +
+					vpfe->field_off;
+
+	vpfe_set_sdr_addr(&vpfe->ccdc, addr);
+}
+
+/*
+ * vpfe_process_buffer_complete: process a completed buffer
+ * @vpfe : ptr to vpfe device
+ *
+ * This function time stamp the buffer and mark it as DONE. It also
+ * wake up any process waiting on the QUEUE and set the next buffer
+ * as current
+ */
+static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe)
+{
+	v4l2_get_timestamp(&vpfe->cur_frm->vb.v4l2_buf.timestamp);
+	vpfe->cur_frm->vb.v4l2_buf.field = vpfe->fmt.fmt.pix.field;
+	vpfe->cur_frm->vb.v4l2_buf.sequence = vpfe->sequence++;
+	vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_DONE);
+	vpfe->cur_frm = vpfe->next_frm;
+}
+
+/*
+ * vpfe_isr : ISR handler for vpfe capture (VINT0)
+ * @irq: irq number
+ * @dev_id: dev_id ptr
+ *
+ * It changes status of the captured buffer, takes next buffer from the queue
+ * and sets its address in VPFE registers
+ */
+static irqreturn_t vpfe_isr(int irq, void *dev)
+{
+	struct vpfe_device *vpfe = (struct vpfe_device *)dev;
+	enum v4l2_field field;
+	int intr_status;
+	int fid;
+
+	intr_status = vpfe_reg_read(&vpfe->ccdc, VPFE_IRQ_STS);
+
+	if (intr_status & VPFE_VDINT0) {
+		field = vpfe->fmt.fmt.pix.field;
+
+		if (field == V4L2_FIELD_NONE) {
+			/* handle progressive frame capture */
+			if (vpfe->cur_frm != vpfe->next_frm)
+				vpfe_process_buffer_complete(vpfe);
+			goto next_intr;
+		}
+
+		/* interlaced or TB capture check which field
+		   we are in hardware */
+		fid = vpfe_ccdc_getfid(&vpfe->ccdc);
+
+		/* switch the software maintained field id */
+		vpfe->field ^= 1;
+		if (fid == vpfe->field) {
+			/* we are in-sync here,continue */
+			if (fid == 0) {
+				/*
+				 * One frame is just being captured. If the
+				 * next frame is available, release the
+				 * current frame and move on
+				 */
+				if (vpfe->cur_frm != vpfe->next_frm)
+					vpfe_process_buffer_complete(vpfe);
+				/*
+				 * based on whether the two fields are stored
+				 * interleave or separately in memory,
+				 * reconfigure the CCDC memory address
+				 */
+				if (field == V4L2_FIELD_SEQ_TB)
+					vpfe_schedule_bottom_field(vpfe);
+
+				goto next_intr;
+			}
+			/*
+			 * if one field is just being captured configure
+			 * the next frame get the next frame from the empty
+			 * queue if no frame is available hold on to the
+			 * current buffer
+			 */
+			spin_lock(&vpfe->dma_queue_lock);
+			if (!list_empty(&vpfe->dma_queue) &&
+			    vpfe->cur_frm == vpfe->next_frm)
+				vpfe_schedule_next_buffer(vpfe);
+			spin_unlock(&vpfe->dma_queue_lock);
+		} else if (fid == 0) {
+			/*
+			 * out of sync. Recover from any hardware out-of-sync.
+			 * May loose one frame
+			 */
+			vpfe->field = fid;
+		}
+	}
+
+next_intr:
+	if (intr_status & VPFE_VDINT1) {
+		spin_lock(&vpfe->dma_queue_lock);
+		if (vpfe->fmt.fmt.pix.field == V4L2_FIELD_NONE &&
+		    !list_empty(&vpfe->dma_queue) &&
+		    vpfe->cur_frm == vpfe->next_frm)
+			vpfe_schedule_next_buffer(vpfe);
+		spin_unlock(&vpfe->dma_queue_lock);
+	}
+
+	vpfe_clear_intr(&vpfe->ccdc, intr_status);
+
+	return IRQ_HANDLED;
+}
+
+static inline void vpfe_detach_irq(struct vpfe_device *vpfe)
+{
+	unsigned int intr = VPFE_VDINT0;
+	enum ccdc_frmfmt frame_format;
+
+	frame_format = vpfe_ccdc_get_frame_format(&vpfe->ccdc);
+	if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
+		intr |= VPFE_VDINT1;
+
+	vpfe_reg_write(&vpfe->ccdc, intr, VPFE_IRQ_EN_CLR);
+}
+
+static inline void vpfe_attach_irq(struct vpfe_device *vpfe)
+{
+	unsigned int intr = VPFE_VDINT0;
+	enum ccdc_frmfmt frame_format;
+
+	frame_format = vpfe_ccdc_get_frame_format(&vpfe->ccdc);
+	if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
+		intr |= VPFE_VDINT1;
+
+	vpfe_reg_write(&vpfe->ccdc, intr, VPFE_IRQ_EN_SET);
+}
+
+static int vpfe_querycap(struct file *file, void  *priv,
+			 struct v4l2_capability *cap)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+
+	vpfe_dbg(2, vpfe, "vpfe_querycap\n");
+
+	strlcpy(cap->driver, VPFE_MODULE_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, "TI AM437x VPFE", sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+			"platform:%s", vpfe->v4l2_dev.name);
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_READWRITE;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+/* get the format set at output pad of the adjacent subdev */
+static int __vpfe_get_format(struct vpfe_device *vpfe,
+			     struct v4l2_format *format, unsigned int *bpp)
+{
+	struct v4l2_mbus_framefmt mbus_fmt;
+	struct vpfe_subdev_info *sdinfo;
+	struct v4l2_subdev_format fmt;
+	int ret;
+
+	sdinfo = vpfe->current_subdev;
+	if (!sdinfo->sd)
+		return -EINVAL;
+
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	fmt.pad = 0;
+
+	ret = v4l2_subdev_call(sdinfo->sd, pad, get_fmt, NULL, &fmt);
+	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		return ret;
+
+	if (!ret) {
+		v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
+		mbus_to_pix(vpfe, &fmt.format, &format->fmt.pix, bpp);
+	} else {
+		ret = v4l2_device_call_until_err(&vpfe->v4l2_dev,
+						 sdinfo->grp_id,
+						 video, g_mbus_fmt,
+						 &mbus_fmt);
+		if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+			return ret;
+		v4l2_fill_pix_format(&format->fmt.pix, &mbus_fmt);
+		mbus_to_pix(vpfe, &mbus_fmt, &format->fmt.pix, bpp);
+	}
+
+	format->type = vpfe->fmt.type;
+
+	vpfe_dbg(1, vpfe,
+		 "%s size %dx%d (%s) bytesperline = %d, size = %d, bpp = %d\n",
+		 __func__, format->fmt.pix.width, format->fmt.pix.height,
+		 print_fourcc(format->fmt.pix.pixelformat),
+		 format->fmt.pix.bytesperline, format->fmt.pix.sizeimage, *bpp);
+
+	return 0;
+}
+
+/* set the format at output pad of the adjacent subdev */
+static int __vpfe_set_format(struct vpfe_device *vpfe,
+			     struct v4l2_format *format, unsigned int *bpp)
+{
+	struct v4l2_mbus_framefmt mbus_fmt;
+	struct vpfe_subdev_info *sdinfo;
+	struct v4l2_subdev_format fmt;
+	int ret;
+
+	vpfe_dbg(2, vpfe, "__vpfe_set_format\n");
+
+	sdinfo = vpfe->current_subdev;
+	if (!sdinfo->sd)
+		return -EINVAL;
+
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	fmt.pad = 0;
+
+	pix_to_mbus(vpfe, &format->fmt.pix, &fmt.format);
+
+	ret = v4l2_subdev_call(sdinfo->sd, pad, set_fmt, NULL, &fmt);
+	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		return ret;
+
+	if (!ret) {
+		v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
+		mbus_to_pix(vpfe, &fmt.format, &format->fmt.pix, bpp);
+	} else {
+		ret = v4l2_device_call_until_err(&vpfe->v4l2_dev,
+						 sdinfo->grp_id,
+						 video, s_mbus_fmt,
+						 &mbus_fmt);
+		if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+			return ret;
+
+		v4l2_fill_pix_format(&format->fmt.pix, &mbus_fmt);
+		mbus_to_pix(vpfe, &mbus_fmt, &format->fmt.pix, bpp);
+	}
+
+	format->type = vpfe->fmt.type;
+
+	vpfe_dbg(1, vpfe,
+		 "%s size %dx%d (%s) bytesperline = %d, size = %d, bpp = %d\n",
+		 __func__,  format->fmt.pix.width, format->fmt.pix.height,
+		 print_fourcc(format->fmt.pix.pixelformat),
+		 format->fmt.pix.bytesperline, format->fmt.pix.sizeimage, *bpp);
+
+	return 0;
+}
+
+static int vpfe_g_fmt(struct file *file, void *priv,
+		      struct v4l2_format *fmt)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+
+	vpfe_dbg(2, vpfe, "vpfe_g_fmt\n");
+
+	*fmt = vpfe->fmt;
+
+	return 0;
+}
+
+static int vpfe_enum_fmt(struct file *file, void  *priv,
+			 struct v4l2_fmtdesc *f)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct vpfe_subdev_info *sdinfo;
+	struct vpfe_fmt *fmt = NULL;
+	unsigned int k;
+
+	vpfe_dbg(2, vpfe, "vpfe_enum_format index:%d\n",
+		f->index);
+
+	sdinfo = vpfe->current_subdev;
+	if (!sdinfo->sd)
+		return -EINVAL;
+
+	if (f->index > ARRAY_SIZE(formats))
+		return -EINVAL;
+
+	for (k = 0; k < ARRAY_SIZE(formats); k++) {
+		if (formats[k].index == f->index) {
+			fmt = &formats[k];
+			break;
+		}
+	}
+	if (!fmt)
+		return -EINVAL;
+
+	strncpy(f->description, fmt->name, sizeof(f->description) - 1);
+	f->pixelformat = fmt->fourcc;
+	f->type = vpfe->fmt.type;
+
+	vpfe_dbg(1, vpfe, "vpfe_enum_format: mbus index: %d code: %x pixelformat: %s [%s]\n",
+		f->index, fmt->code, print_fourcc(fmt->fourcc), fmt->name);
+
+	return 0;
+}
+
+static int vpfe_try_fmt(struct file *file, void *priv,
+			struct v4l2_format *fmt)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	unsigned int bpp;
+
+	vpfe_dbg(2, vpfe, "vpfe_try_fmt\n");
+
+	return __vpfe_get_format(vpfe, fmt, &bpp);
+}
+
+static int vpfe_s_fmt(struct file *file, void *priv,
+		      struct v4l2_format *fmt)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct v4l2_format format;
+	unsigned int bpp;
+	int ret;
+
+	vpfe_dbg(2, vpfe, "vpfe_s_fmt\n");
+
+	/* If streaming is started, return error */
+	if (vb2_is_busy(&vpfe->buffer_queue)) {
+		vpfe_err(vpfe, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	ret = vpfe_try_fmt(file, priv, fmt);
+	if (ret)
+		return ret;
+
+
+	if (!cmp_v4l2_format(fmt, &format)) {
+		/* Sensor format is different from the requested format
+		 * so we need to change it
+		 */
+		ret = __vpfe_set_format(vpfe, fmt, &bpp);
+		if (ret)
+			return ret;
+	} else /* Just make sure all of the fields are consistent */
+		*fmt = format;
+
+	/* First detach any IRQ if currently attached */
+	vpfe_detach_irq(vpfe);
+	vpfe->fmt = *fmt;
+	vpfe->bpp = bpp;
+
+	/* Update the crop window based on found values */
+	vpfe->crop.width = fmt->fmt.pix.width;
+	vpfe->crop.height = fmt->fmt.pix.height;
+
+	/* set image capture parameters in the ccdc */
+	return vpfe_config_ccdc_image_format(vpfe);
+}
+
+static int vpfe_enum_size(struct file *file, void  *priv,
+			  struct v4l2_frmsizeenum *fsize)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct v4l2_subdev_frame_size_enum fse;
+	struct vpfe_subdev_info *sdinfo;
+	struct v4l2_mbus_framefmt mbus;
+	struct v4l2_pix_format pix;
+	struct vpfe_fmt *fmt;
+	int ret;
+
+	vpfe_dbg(2, vpfe, "vpfe_enum_size\n");
+
+	/* check for valid format */
+	fmt = find_format_by_pix(fsize->pixel_format);
+	if (!fmt) {
+		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
+			fsize->pixel_format);
+		return -EINVAL;
+	}
+
+	memset(fsize->reserved, 0x0, sizeof(fsize->reserved));
+
+	sdinfo = vpfe->current_subdev;
+	if (!sdinfo->sd)
+		return -EINVAL;
+
+	memset(&pix, 0x0, sizeof(pix));
+	/* Construct pix from parameter and use default for the rest */
+	pix.pixelformat = fsize->pixel_format;
+	pix.width = 640;
+	pix.height = 480;
+	pix.colorspace = V4L2_COLORSPACE_SRGB;
+	pix.field = V4L2_FIELD_NONE;
+	pix_to_mbus(vpfe, &pix, &mbus);
+
+	memset(&fse, 0x0, sizeof(fse));
+	fse.index = fsize->index;
+	fse.pad = 0;
+	fse.code = mbus.code;
+	ret = v4l2_subdev_call(sdinfo->sd, pad, enum_frame_size, NULL, &fse);
+	if (ret)
+		return -EINVAL;
+
+	vpfe_dbg(1, vpfe, "vpfe_enum_size: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
+		fse.index, fse.code, fse.min_width, fse.max_width,
+		fse.min_height, fse.max_height);
+
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete.width = fse.max_width;
+	fsize->discrete.height = fse.max_height;
+
+	vpfe_dbg(1, vpfe, "vpfe_enum_size: index: %d pixformat: %s size: %dx%d\n",
+		fsize->index, print_fourcc(fsize->pixel_format),
+		fsize->discrete.width, fsize->discrete.height);
+
+	return 0;
+}
+
+/*
+ * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a
+ * given app input index
+ */
+static int
+vpfe_get_subdev_input_index(struct vpfe_device *vpfe,
+			    int *subdev_index,
+			    int *subdev_input_index,
+			    int app_input_index)
+{
+	struct vpfe_config *cfg = vpfe->cfg;
+	struct vpfe_subdev_info *sdinfo;
+	int i, j = 0;
+
+	for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
+		sdinfo = &cfg->sub_devs[i];
+		if (app_input_index < (j + 1)) {
+			*subdev_index = i;
+			*subdev_input_index = app_input_index - j;
+			return 0;
+		}
+		j++;
+	}
+	return -EINVAL;
+}
+
+/*
+ * vpfe_get_app_input - Get app input index for a given subdev input index
+ * driver stores the input index of the current sub device and translate it
+ * when application request the current input
+ */
+static int vpfe_get_app_input_index(struct vpfe_device *vpfe,
+				    int *app_input_index)
+{
+	struct vpfe_config *cfg = vpfe->cfg;
+	struct vpfe_subdev_info *sdinfo;
+	int i, j = 0;
+
+	for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
+		sdinfo = &cfg->sub_devs[i];
+		if (!strcmp(sdinfo->name, vpfe->current_subdev->name)) {
+			if (vpfe->current_input >= 1)
+				return -1;
+			*app_input_index = j + vpfe->current_input;
+			return 0;
+		}
+		j++;
+	}
+	return -EINVAL;
+}
+
+static int vpfe_enum_input(struct file *file, void *priv,
+			   struct v4l2_input *inp)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct vpfe_subdev_info *sdinfo;
+	int subdev, index;
+
+	vpfe_dbg(2, vpfe, "vpfe_enum_input\n");
+
+	if (vpfe_get_subdev_input_index(vpfe, &subdev, &index,
+					inp->index) < 0) {
+		vpfe_dbg(1, vpfe,
+			"input information not found for the subdev\n");
+		return -EINVAL;
+	}
+	sdinfo = &vpfe->cfg->sub_devs[subdev];
+	*inp = sdinfo->inputs[index];
+
+	return 0;
+}
+
+static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+
+	vpfe_dbg(2, vpfe, "vpfe_g_input\n");
+
+	return vpfe_get_app_input_index(vpfe, index);
+}
+
+/* Assumes caller is holding vpfe_dev->lock */
+static int vpfe_set_input(struct vpfe_device *vpfe, unsigned int index)
+{
+	int subdev_index = 0, inp_index = 0;
+	struct vpfe_subdev_info *sdinfo;
+	struct vpfe_route *route;
+	u32 input, output;
+	int ret;
+
+	vpfe_dbg(2, vpfe, "vpfe_set_input: index: %d\n", index);
+
+	/* If streaming is started, return error */
+	if (vb2_is_busy(&vpfe->buffer_queue)) {
+		vpfe_err(vpfe, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+	ret = vpfe_get_subdev_input_index(vpfe,
+					  &subdev_index,
+					  &inp_index,
+					  index);
+	if (ret < 0) {
+		vpfe_err(vpfe, "invalid input index: %d\n", index);
+		goto get_out;
+	}
+
+	sdinfo = &vpfe->cfg->sub_devs[subdev_index];
+	sdinfo->sd = vpfe->sd[subdev_index];
+	route = &sdinfo->routes[inp_index];
+	if (route && sdinfo->can_route) {
+		input = route->input;
+		output = route->output;
+		if (sdinfo->sd) {
+			ret = v4l2_subdev_call(sdinfo->sd, video,
+					s_routing, input, output, 0);
+			if (ret) {
+				vpfe_err(vpfe, "s_routing failed\n");
+				ret = -EINVAL;
+				goto get_out;
+			}
+		}
+
+	}
+
+	vpfe->current_subdev = sdinfo;
+	if (sdinfo->sd)
+		vpfe->v4l2_dev.ctrl_handler = sdinfo->sd->ctrl_handler;
+	vpfe->current_input = index;
+	vpfe->std_index = 0;
+
+	/* set the bus/interface parameter for the sub device in ccdc */
+	ret = vpfe_ccdc_set_hw_if_params(&vpfe->ccdc, &sdinfo->vpfe_param);
+	if (ret)
+		return ret;
+
+	/* set the default image parameters in the device */
+	return vpfe_config_image_format(vpfe,
+					vpfe_standards[vpfe->std_index].std_id);
+
+get_out:
+	return ret;
+}
+
+static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+
+	vpfe_dbg(2, vpfe,
+		"vpfe_s_input: index: %d\n", index);
+
+	return vpfe_set_input(vpfe, index);
+}
+
+static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct vpfe_subdev_info *sdinfo;
+
+	vpfe_dbg(2, vpfe, "vpfe_querystd\n");
+
+	sdinfo = vpfe->current_subdev;
+	if (!(sdinfo->inputs[0].capabilities & V4L2_IN_CAP_STD))
+		return -ENODATA;
+
+	/* Call querystd function of decoder device */
+	return v4l2_device_call_until_err(&vpfe->v4l2_dev, sdinfo->grp_id,
+					 video, querystd, std_id);
+}
+
+static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct vpfe_subdev_info *sdinfo;
+	int ret;
+
+	vpfe_dbg(2, vpfe, "vpfe_s_std\n");
+
+	sdinfo = vpfe->current_subdev;
+	if (!(sdinfo->inputs[0].capabilities & V4L2_IN_CAP_STD))
+		return -ENODATA;
+
+	/* If streaming is started, return error */
+	if (vb2_is_busy(&vpfe->buffer_queue)) {
+		vpfe_err(vpfe, "%s device busy\n", __func__);
+		ret = -EBUSY;
+		return ret;
+	}
+
+	ret = v4l2_device_call_until_err(&vpfe->v4l2_dev, sdinfo->grp_id,
+					 video, s_std, std_id);
+	if (ret < 0) {
+		vpfe_err(vpfe, "Failed to set standard\n");
+		return ret;
+	}
+	ret = vpfe_config_image_format(vpfe, std_id);
+
+	return ret;
+}
+
+static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct vpfe_subdev_info *sdinfo;
+
+	vpfe_dbg(2, vpfe, "vpfe_g_std\n");
+
+	sdinfo = vpfe->current_subdev;
+	if (sdinfo->inputs[0].capabilities != V4L2_IN_CAP_STD)
+		return -ENODATA;
+
+	*std_id = vpfe_standards[vpfe->std_index].std_id;
+
+	return 0;
+}
+
+/*
+ * vpfe_calculate_offsets : This function calculates buffers offset
+ * for top and bottom field
+ */
+static void vpfe_calculate_offsets(struct vpfe_device *vpfe)
+{
+	struct v4l2_rect image_win;
+
+	vpfe_dbg(2, vpfe, "vpfe_calculate_offsets\n");
+
+	vpfe_ccdc_get_image_window(&vpfe->ccdc, &image_win);
+	vpfe->field_off = image_win.height * image_win.width;
+}
+
+/*
+ * vpfe_queue_setup - Callback function for buffer setup.
+ * @vq: vb2_queue ptr
+ * @fmt: v4l2 format
+ * @nbuffers: ptr to number of buffers requested by application
+ * @nplanes:: contains number of distinct video planes needed to hold a frame
+ * @sizes[]: contains the size (in bytes) of each plane.
+ * @alloc_ctxs: ptr to allocation context
+ *
+ * This callback function is called when reqbuf() is called to adjust
+ * the buffer count and buffer size
+ */
+static int vpfe_queue_setup(struct vb2_queue *vq,
+			    const struct v4l2_format *fmt,
+			    unsigned int *nbuffers, unsigned int *nplanes,
+			    unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
+
+	if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage)
+		return -EINVAL;
+
+	if (vq->num_buffers + *nbuffers < 3)
+		*nbuffers = 3 - vq->num_buffers;
+
+	*nplanes = 1;
+	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : vpfe->fmt.fmt.pix.sizeimage;
+	alloc_ctxs[0] = vpfe->alloc_ctx;
+
+	vpfe_dbg(1, vpfe,
+		"nbuffers=%d, size=%u\n", *nbuffers, sizes[0]);
+
+	/* Calculate field offset */
+	vpfe_calculate_offsets(vpfe);
+
+	return 0;
+}
+
+/*
+ * vpfe_buffer_prepare :  callback function for buffer prepare
+ * @vb: ptr to vb2_buffer
+ *
+ * This is the callback function for buffer prepare when vb2_qbuf()
+ * function is called. The buffer is prepared and user space virtual address
+ * or user address is converted into  physical address
+ */
+static int vpfe_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue);
+
+	vb2_set_plane_payload(vb, 0, vpfe->fmt.fmt.pix.sizeimage);
+
+	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
+		return -EINVAL;
+
+	vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field;
+
+	return 0;
+}
+
+/*
+ * vpfe_buffer_queue : Callback function to add buffer to DMA queue
+ * @vb: ptr to vb2_buffer
+ */
+static void vpfe_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue);
+	struct vpfe_cap_buffer *buf = to_vpfe_buffer(vb);
+	unsigned long flags = 0;
+
+	/* add the buffer to the DMA queue */
+	spin_lock_irqsave(&vpfe->dma_queue_lock, flags);
+	list_add_tail(&buf->list, &vpfe->dma_queue);
+	spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags);
+}
+
+/*
+ * vpfe_start_streaming : Starts the DMA engine for streaming
+ * @vb: ptr to vb2_buffer
+ * @count: number of buffers
+ */
+static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
+	struct vpfe_cap_buffer *buf, *tmp;
+	struct vpfe_subdev_info *sdinfo;
+	unsigned long flags;
+	unsigned long addr;
+	int ret;
+
+	spin_lock_irqsave(&vpfe->dma_queue_lock, flags);
+
+	vpfe->field = 0;
+	vpfe->sequence = 0;
+
+	sdinfo = vpfe->current_subdev;
+
+	vpfe_attach_irq(vpfe);
+
+	if (vpfe->ccdc.ccdc_cfg.if_type == VPFE_RAW_BAYER)
+		vpfe_ccdc_config_raw(&vpfe->ccdc);
+	else
+		vpfe_ccdc_config_ycbcr(&vpfe->ccdc);
+
+	/* Get the next frame from the buffer queue */
+	vpfe->next_frm = list_entry(vpfe->dma_queue.next,
+				    struct vpfe_cap_buffer, list);
+	vpfe->cur_frm = vpfe->next_frm;
+	/* Remove buffer from the buffer queue */
+	list_del(&vpfe->cur_frm->list);
+	spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags);
+
+	addr = vb2_dma_contig_plane_dma_addr(&vpfe->cur_frm->vb, 0);
+
+	vpfe_set_sdr_addr(&vpfe->ccdc, (unsigned long)(addr));
+
+	vpfe_pcr_enable(&vpfe->ccdc, 1);
+
+	ret = v4l2_subdev_call(sdinfo->sd, video, s_stream, 1);
+	if (ret < 0) {
+		vpfe_err(vpfe, "Error in attaching interrupt handle\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	list_for_each_entry_safe(buf, tmp, &vpfe->dma_queue, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+	}
+
+	return ret;
+}
+
+/*
+ * vpfe_stop_streaming : Stop the DMA engine
+ * @vq: ptr to vb2_queue
+ *
+ * This callback stops the DMA engine and any remaining buffers
+ * in the DMA queue are released.
+ */
+static void vpfe_stop_streaming(struct vb2_queue *vq)
+{
+	struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
+	struct vpfe_subdev_info *sdinfo;
+	unsigned long flags;
+	int ret;
+
+	vpfe_pcr_enable(&vpfe->ccdc, 0);
+
+	vpfe_detach_irq(vpfe);
+
+	sdinfo = vpfe->current_subdev;
+	ret = v4l2_subdev_call(sdinfo->sd, video, s_stream, 0);
+	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		vpfe_dbg(1, vpfe, "stream off failed in subdev\n");
+
+	/* release all active buffers */
+	spin_lock_irqsave(&vpfe->dma_queue_lock, flags);
+	if (vpfe->cur_frm == vpfe->next_frm) {
+		vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_ERROR);
+	} else {
+		if (vpfe->cur_frm != NULL)
+			vb2_buffer_done(&vpfe->cur_frm->vb,
+					VB2_BUF_STATE_ERROR);
+		if (vpfe->next_frm != NULL)
+			vb2_buffer_done(&vpfe->next_frm->vb,
+					VB2_BUF_STATE_ERROR);
+	}
+
+	while (!list_empty(&vpfe->dma_queue)) {
+		vpfe->next_frm = list_entry(vpfe->dma_queue.next,
+						struct vpfe_cap_buffer, list);
+		list_del(&vpfe->next_frm->list);
+		vb2_buffer_done(&vpfe->next_frm->vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags);
+}
+
+static int vpfe_cropcap(struct file *file, void *priv,
+			struct v4l2_cropcap *crop)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+
+	vpfe_dbg(2, vpfe, "vpfe_cropcap\n");
+
+	if (vpfe->std_index >= ARRAY_SIZE(vpfe_standards))
+		return -EINVAL;
+
+	memset(crop, 0, sizeof(struct v4l2_cropcap));
+
+	crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	crop->defrect.width = vpfe_standards[vpfe->std_index].width;
+	crop->bounds.width = crop->defrect.width;
+	crop->defrect.height = vpfe_standards[vpfe->std_index].height;
+	crop->bounds.height = crop->defrect.height;
+	crop->pixelaspect = vpfe_standards[vpfe->std_index].pixelaspect;
+
+	return 0;
+}
+
+static int
+vpfe_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		s->r.left = s->r.top = 0;
+		s->r.width = vpfe->crop.width;
+		s->r.height = vpfe->crop.height;
+		break;
+
+	case V4L2_SEL_TGT_CROP:
+		s->r = vpfe->crop;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
+{
+	if (a->left < b->left || a->top < b->top)
+		return 0;
+
+	if (a->left + a->width > b->left + b->width)
+		return 0;
+
+	if (a->top + a->height > b->top + b->height)
+		return 0;
+
+	return 1;
+}
+
+static int
+vpfe_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	struct v4l2_rect cr = vpfe->crop;
+	struct v4l2_rect r = s->r;
+
+	/* If streaming is started, return error */
+	if (vb2_is_busy(&vpfe->buffer_queue)) {
+		vpfe_err(vpfe, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+			s->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	v4l_bound_align_image(&r.width, 0, cr.width, 0,
+			      &r.height, 0, cr.height, 0, 0);
+
+	r.left = clamp_t(unsigned int, r.left, 0, cr.width - r.width);
+	r.top  = clamp_t(unsigned int, r.top, 0, cr.height - r.height);
+
+	if (s->flags & V4L2_SEL_FLAG_LE && !enclosed_rectangle(&r, &s->r))
+		return -ERANGE;
+
+	if (s->flags & V4L2_SEL_FLAG_GE && !enclosed_rectangle(&s->r, &r))
+		return -ERANGE;
+
+	s->r = vpfe->crop = r;
+
+	vpfe_ccdc_set_image_window(&vpfe->ccdc, &r, vpfe->bpp);
+	vpfe->fmt.fmt.pix.width = r.width;
+	vpfe->fmt.fmt.pix.height = r.height;
+	vpfe->fmt.fmt.pix.bytesperline = vpfe_ccdc_get_line_length(&vpfe->ccdc);
+	vpfe->fmt.fmt.pix.sizeimage = vpfe->fmt.fmt.pix.bytesperline *
+						vpfe->fmt.fmt.pix.height;
+
+	vpfe_dbg(1, vpfe, "cropped (%d,%d)/%dx%d of %dx%d\n",
+		 r.left, r.top, r.width, r.height, cr.width, cr.height);
+
+	return 0;
+}
+
+static long vpfe_ioctl_default(struct file *file, void *priv,
+			       bool valid_prio, unsigned int cmd, void *param)
+{
+	struct vpfe_device *vpfe = video_drvdata(file);
+	int ret;
+
+	vpfe_dbg(2, vpfe, "vpfe_ioctl_default\n");
+
+	if (!valid_prio) {
+		vpfe_err(vpfe, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	/* If streaming is started, return error */
+	if (vb2_is_busy(&vpfe->buffer_queue)) {
+		vpfe_err(vpfe, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	switch (cmd) {
+	case VIDIOC_AM437X_CCDC_CFG:
+		ret = vpfe_ccdc_set_params(&vpfe->ccdc, (void __user *)param);
+		if (ret) {
+			vpfe_dbg(2, vpfe,
+				"Error setting parameters in CCDC\n");
+			return ret;
+		}
+		ret = vpfe_get_ccdc_image_format(vpfe,
+						 &vpfe->fmt);
+		if (ret < 0) {
+			vpfe_dbg(2, vpfe,
+				"Invalid image format at CCDC\n");
+			return ret;
+		}
+		break;
+
+	default:
+		ret = -ENOTTY;
+		break;
+	}
+
+	return ret;
+}
+
+static const struct vb2_ops vpfe_video_qops = {
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+	.queue_setup		= vpfe_queue_setup,
+	.buf_prepare		= vpfe_buffer_prepare,
+	.buf_queue		= vpfe_buffer_queue,
+	.start_streaming	= vpfe_start_streaming,
+	.stop_streaming		= vpfe_stop_streaming,
+};
+
+/* vpfe capture driver file operations */
+static const struct v4l2_file_operations vpfe_fops = {
+	.owner		= THIS_MODULE,
+	.open		= vpfe_open,
+	.release	= vpfe_release,
+	.read		= vb2_fop_read,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= vb2_fop_mmap,
+};
+
+/* vpfe capture ioctl operations */
+static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
+	.vidioc_querycap		= vpfe_querycap,
+	.vidioc_enum_fmt_vid_cap	= vpfe_enum_fmt,
+	.vidioc_g_fmt_vid_cap		= vpfe_g_fmt,
+	.vidioc_s_fmt_vid_cap		= vpfe_s_fmt,
+	.vidioc_try_fmt_vid_cap		= vpfe_try_fmt,
+
+	.vidioc_enum_framesizes		= vpfe_enum_size,
+
+	.vidioc_enum_input		= vpfe_enum_input,
+	.vidioc_g_input			= vpfe_g_input,
+	.vidioc_s_input			= vpfe_s_input,
+
+	.vidioc_querystd		= vpfe_querystd,
+	.vidioc_s_std			= vpfe_s_std,
+	.vidioc_g_std			= vpfe_g_std,
+
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_expbuf			= vb2_ioctl_expbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+
+	.vidioc_cropcap			= vpfe_cropcap,
+	.vidioc_g_selection		= vpfe_g_selection,
+	.vidioc_s_selection		= vpfe_s_selection,
+
+	.vidioc_default			= vpfe_ioctl_default,
+};
+
+static int
+vpfe_async_bound(struct v4l2_async_notifier *notifier,
+		 struct v4l2_subdev *subdev,
+		 struct v4l2_async_subdev *asd)
+{
+	struct vpfe_device *vpfe = container_of(notifier->v4l2_dev,
+					       struct vpfe_device, v4l2_dev);
+	struct v4l2_subdev_mbus_code_enum mbus_code;
+	struct vpfe_subdev_info *sdinfo;
+	bool found = false;
+	int i, j;
+
+	vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
+
+	for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
+		sdinfo = &vpfe->cfg->sub_devs[i];
+
+		if (!strcmp(sdinfo->name, subdev->name)) {
+			vpfe->sd[i] = subdev;
+			vpfe_info(vpfe,
+				 "v4l2 sub device %s registered\n",
+				 subdev->name);
+			vpfe->sd[i]->grp_id =
+					sdinfo->grp_id;
+			/* update tvnorms from the sub devices */
+			for (j = 0; j < 1; j++)
+				vpfe->video_dev->tvnorms |=
+					sdinfo->inputs[j].std;
+
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		vpfe_info(vpfe, "sub device (%s) not matched\n", subdev->name);
+		return -EINVAL;
+	}
+
+	/* setup the supported formats & indexes */
+	for (j = 0, i = 0; ; ++j) {
+		struct vpfe_fmt *fmt;
+		int ret;
+
+		memset(&mbus_code, 0, sizeof(mbus_code));
+		mbus_code.index = j;
+		ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
+			       NULL, &mbus_code);
+		if (ret)
+			break;
+
+		fmt = find_format_by_code(mbus_code.code);
+		if (!fmt)
+			continue;
+
+		fmt->supported = true;
+		fmt->index = i++;
+	}
+
+	return 0;
+}
+
+static int vpfe_probe_complete(struct vpfe_device *vpfe)
+{
+	struct video_device *vdev;
+	struct vb2_queue *q;
+	int err;
+
+	spin_lock_init(&vpfe->dma_queue_lock);
+	mutex_init(&vpfe->lock);
+
+	vpfe->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	/* set first sub device as current one */
+	vpfe->current_subdev = &vpfe->cfg->sub_devs[0];
+	vpfe->v4l2_dev.ctrl_handler = vpfe->sd[0]->ctrl_handler;
+
+	err = vpfe_set_input(vpfe, 0);
+	if (err)
+		goto probe_out;
+
+	/* Initialize videobuf2 queue as per the buffer type */
+	vpfe->alloc_ctx = vb2_dma_contig_init_ctx(vpfe->pdev);
+	if (IS_ERR(vpfe->alloc_ctx)) {
+		vpfe_err(vpfe, "Failed to get the context\n");
+		err = PTR_ERR(vpfe->alloc_ctx);
+		goto probe_out;
+	}
+
+	q = &vpfe->buffer_queue;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+	q->drv_priv = vpfe;
+	q->ops = &vpfe_video_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct vpfe_cap_buffer);
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &vpfe->lock;
+	q->min_buffers_needed = 1;
+
+	err = vb2_queue_init(q);
+	if (err) {
+		vpfe_err(vpfe, "vb2_queue_init() failed\n");
+		vb2_dma_contig_cleanup_ctx(vpfe->alloc_ctx);
+		goto probe_out;
+	}
+
+	INIT_LIST_HEAD(&vpfe->dma_queue);
+
+	vdev = vpfe->video_dev;
+	strlcpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name));
+	vdev->release = video_device_release;
+	vdev->fops = &vpfe_fops;
+	vdev->ioctl_ops = &vpfe_ioctl_ops;
+	vdev->v4l2_dev = &vpfe->v4l2_dev;
+	vdev->vfl_dir = VFL_DIR_RX;
+	vdev->queue = q;
+	vdev->lock = &vpfe->lock;
+	video_set_drvdata(vdev, vpfe);
+	err = video_register_device(vpfe->video_dev, VFL_TYPE_GRABBER, -1);
+	if (err) {
+		vpfe_err(vpfe,
+			"Unable to register video device.\n");
+		goto probe_out;
+	}
+
+	return 0;
+
+probe_out:
+	v4l2_device_unregister(&vpfe->v4l2_dev);
+	return err;
+}
+
+static int vpfe_async_complete(struct v4l2_async_notifier *notifier)
+{
+	struct vpfe_device *vpfe = container_of(notifier->v4l2_dev,
+					struct vpfe_device, v4l2_dev);
+
+	return vpfe_probe_complete(vpfe);
+}
+
+static struct vpfe_config *
+vpfe_get_pdata(struct platform_device *pdev)
+{
+	struct device_node *endpoint = NULL, *rem = NULL;
+	struct v4l2_of_endpoint bus_cfg;
+	struct vpfe_subdev_info *sdinfo;
+	struct vpfe_config *pdata;
+	unsigned int flags;
+	unsigned int i;
+	int err;
+
+	dev_dbg(&pdev->dev, "vpfe_get_pdata\n");
+
+	if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node)
+		return pdev->dev.platform_data;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	for (i = 0; ; i++) {
+		endpoint = of_graph_get_next_endpoint(pdev->dev.of_node,
+						      endpoint);
+		if (!endpoint)
+			break;
+
+		sdinfo = &pdata->sub_devs[i];
+		sdinfo->grp_id = 0;
+
+		/* we only support camera */
+		sdinfo->inputs[0].index = i;
+		strcpy(sdinfo->inputs[0].name, "Camera");
+		sdinfo->inputs[0].type = V4L2_INPUT_TYPE_CAMERA;
+		sdinfo->inputs[0].std = V4L2_STD_ALL;
+		sdinfo->inputs[0].capabilities = V4L2_IN_CAP_STD;
+
+		sdinfo->can_route = 0;
+		sdinfo->routes = NULL;
+
+		of_property_read_u32(endpoint, "ti,am437x-vpfe-interface",
+				     &sdinfo->vpfe_param.if_type);
+		if (sdinfo->vpfe_param.if_type < 0 ||
+			sdinfo->vpfe_param.if_type > 4) {
+			sdinfo->vpfe_param.if_type = VPFE_RAW_BAYER;
+		}
+
+		err = v4l2_of_parse_endpoint(endpoint, &bus_cfg);
+		if (err) {
+			dev_err(&pdev->dev, "Could not parse the endpoint\n");
+			goto done;
+		}
+
+		sdinfo->vpfe_param.bus_width = bus_cfg.bus.parallel.bus_width;
+
+		if (sdinfo->vpfe_param.bus_width < 8 ||
+			sdinfo->vpfe_param.bus_width > 16) {
+			dev_err(&pdev->dev, "Invalid bus width.\n");
+			goto done;
+		}
+
+		flags = bus_cfg.bus.parallel.flags;
+
+		if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+			sdinfo->vpfe_param.hdpol = 1;
+
+		if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+			sdinfo->vpfe_param.vdpol = 1;
+
+		rem = of_graph_get_remote_port_parent(endpoint);
+		if (!rem) {
+			dev_err(&pdev->dev, "Remote device at %s not found\n",
+				endpoint->full_name);
+			goto done;
+		}
+
+		strncpy(sdinfo->name, rem->name, sizeof(sdinfo->name));
+
+		pdata->asd[i] = devm_kzalloc(&pdev->dev,
+					     sizeof(struct v4l2_async_subdev),
+					     GFP_KERNEL);
+		pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_OF;
+		pdata->asd[i]->match.of.node = rem;
+		of_node_put(endpoint);
+		of_node_put(rem);
+	}
+
+	of_node_put(endpoint);
+	return pdata;
+
+done:
+	of_node_put(endpoint);
+	of_node_put(rem);
+	return NULL;
+}
+
+/*
+ * vpfe_probe : This function creates device entries by register
+ * itself to the V4L2 driver and initializes fields of each
+ * device objects
+ */
+static int vpfe_probe(struct platform_device *pdev)
+{
+	struct vpfe_config *vpfe_cfg = vpfe_get_pdata(pdev);
+	struct vpfe_device *vpfe;
+	struct vpfe_ccdc *ccdc;
+	struct resource	*res;
+	int ret;
+
+	if (!vpfe_cfg) {
+		dev_err(&pdev->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	vpfe = devm_kzalloc(&pdev->dev, sizeof(*vpfe), GFP_KERNEL);
+	if (!vpfe)
+		return -ENOMEM;
+
+	vpfe->pdev = &pdev->dev;
+	vpfe->cfg = vpfe_cfg;
+	ccdc = &vpfe->ccdc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ccdc->ccdc_cfg.base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ccdc->ccdc_cfg.base_addr))
+		return PTR_ERR(ccdc->ccdc_cfg.base_addr);
+
+	vpfe->irq = platform_get_irq(pdev, 0);
+	if (vpfe->irq <= 0) {
+		dev_err(&pdev->dev, "No IRQ resource\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_irq(vpfe->pdev, vpfe->irq, vpfe_isr, 0,
+			       "vpfe_capture0", vpfe);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to request interrupt\n");
+		return -EINVAL;
+	}
+
+	vpfe->video_dev = video_device_alloc();
+	if (!vpfe->video_dev) {
+		dev_err(&pdev->dev, "Unable to allocate video device\n");
+		return -ENOMEM;
+	}
+
+	ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev);
+	if (ret) {
+		vpfe_err(vpfe,
+			"Unable to register v4l2 device.\n");
+		goto probe_out_video_release;
+	}
+
+	/* set the driver data in platform device */
+	platform_set_drvdata(pdev, vpfe);
+	/* Enabling module functional clock */
+	pm_runtime_enable(&pdev->dev);
+
+	/* for now just enable it here instead of waiting for the open */
+	pm_runtime_get_sync(&pdev->dev);
+
+	vpfe_ccdc_config_defaults(ccdc);
+
+	pm_runtime_put_sync(&pdev->dev);
+
+	vpfe->sd = devm_kzalloc(&pdev->dev, sizeof(struct v4l2_subdev *) *
+				ARRAY_SIZE(vpfe->cfg->asd), GFP_KERNEL);
+	if (!vpfe->sd) {
+		ret = -ENOMEM;
+		goto probe_out_v4l2_unregister;
+	}
+
+	vpfe->notifier.subdevs = vpfe->cfg->asd;
+	vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd);
+	vpfe->notifier.bound = vpfe_async_bound;
+	vpfe->notifier.complete = vpfe_async_complete;
+	ret = v4l2_async_notifier_register(&vpfe->v4l2_dev,
+						&vpfe->notifier);
+	if (ret) {
+		vpfe_err(vpfe, "Error registering async notifier\n");
+		ret = -EINVAL;
+		goto probe_out_v4l2_unregister;
+	}
+
+	return 0;
+
+probe_out_v4l2_unregister:
+	v4l2_device_unregister(&vpfe->v4l2_dev);
+probe_out_video_release:
+	if (!video_is_registered(vpfe->video_dev))
+		video_device_release(vpfe->video_dev);
+	return ret;
+}
+
+/*
+ * vpfe_remove : It un-register device from V4L2 driver
+ */
+static int vpfe_remove(struct platform_device *pdev)
+{
+	struct vpfe_device *vpfe = platform_get_drvdata(pdev);
+
+	vpfe_dbg(2, vpfe, "vpfe_remove\n");
+
+	pm_runtime_disable(&pdev->dev);
+
+	v4l2_async_notifier_unregister(&vpfe->notifier);
+	v4l2_device_unregister(&vpfe->v4l2_dev);
+	video_unregister_device(vpfe->video_dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static void vpfe_save_context(struct vpfe_ccdc *ccdc)
+{
+	ccdc->ccdc_ctx[VPFE_PCR >> 2] = vpfe_reg_read(ccdc, VPFE_PCR);
+	ccdc->ccdc_ctx[VPFE_SYNMODE >> 2] = vpfe_reg_read(ccdc, VPFE_SYNMODE);
+	ccdc->ccdc_ctx[VPFE_SDOFST >> 2] = vpfe_reg_read(ccdc, VPFE_SDOFST);
+	ccdc->ccdc_ctx[VPFE_SDR_ADDR >> 2] = vpfe_reg_read(ccdc, VPFE_SDR_ADDR);
+	ccdc->ccdc_ctx[VPFE_CLAMP >> 2] = vpfe_reg_read(ccdc, VPFE_CLAMP);
+	ccdc->ccdc_ctx[VPFE_DCSUB >> 2] = vpfe_reg_read(ccdc, VPFE_DCSUB);
+	ccdc->ccdc_ctx[VPFE_COLPTN >> 2] = vpfe_reg_read(ccdc, VPFE_COLPTN);
+	ccdc->ccdc_ctx[VPFE_BLKCMP >> 2] = vpfe_reg_read(ccdc, VPFE_BLKCMP);
+	ccdc->ccdc_ctx[VPFE_VDINT >> 2] = vpfe_reg_read(ccdc, VPFE_VDINT);
+	ccdc->ccdc_ctx[VPFE_ALAW >> 2] = vpfe_reg_read(ccdc, VPFE_ALAW);
+	ccdc->ccdc_ctx[VPFE_REC656IF >> 2] = vpfe_reg_read(ccdc, VPFE_REC656IF);
+	ccdc->ccdc_ctx[VPFE_CCDCFG >> 2] = vpfe_reg_read(ccdc, VPFE_CCDCFG);
+	ccdc->ccdc_ctx[VPFE_CULLING >> 2] = vpfe_reg_read(ccdc, VPFE_CULLING);
+	ccdc->ccdc_ctx[VPFE_HD_VD_WID >> 2] = vpfe_reg_read(ccdc,
+							    VPFE_HD_VD_WID);
+	ccdc->ccdc_ctx[VPFE_PIX_LINES >> 2] = vpfe_reg_read(ccdc,
+							    VPFE_PIX_LINES);
+	ccdc->ccdc_ctx[VPFE_HORZ_INFO >> 2] = vpfe_reg_read(ccdc,
+							    VPFE_HORZ_INFO);
+	ccdc->ccdc_ctx[VPFE_VERT_START >> 2] = vpfe_reg_read(ccdc,
+							     VPFE_VERT_START);
+	ccdc->ccdc_ctx[VPFE_VERT_LINES >> 2] = vpfe_reg_read(ccdc,
+							     VPFE_VERT_LINES);
+	ccdc->ccdc_ctx[VPFE_HSIZE_OFF >> 2] = vpfe_reg_read(ccdc,
+							    VPFE_HSIZE_OFF);
+}
+
+static int vpfe_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct vpfe_device *vpfe = platform_get_drvdata(pdev);
+	struct vpfe_ccdc *ccdc = &vpfe->ccdc;
+
+	/* if streaming has not started we don't care */
+	if (!vb2_start_streaming_called(&vpfe->buffer_queue))
+		return 0;
+
+	pm_runtime_get_sync(dev);
+	vpfe_config_enable(ccdc, 1);
+
+	/* Save VPFE context */
+	vpfe_save_context(ccdc);
+
+	/* Disable CCDC */
+	vpfe_pcr_enable(ccdc, 0);
+	vpfe_config_enable(ccdc, 0);
+
+	/* Disable both master and slave clock */
+	pm_runtime_put_sync(dev);
+
+	/* Select sleep pin state */
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static void vpfe_restore_context(struct vpfe_ccdc *ccdc)
+{
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_SYNMODE >> 2], VPFE_SYNMODE);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_CULLING >> 2], VPFE_CULLING);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_SDOFST >> 2], VPFE_SDOFST);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_SDR_ADDR >> 2], VPFE_SDR_ADDR);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_CLAMP >> 2], VPFE_CLAMP);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_DCSUB >> 2], VPFE_DCSUB);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_COLPTN >> 2], VPFE_COLPTN);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_BLKCMP >> 2], VPFE_BLKCMP);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_VDINT >> 2], VPFE_VDINT);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_ALAW >> 2], VPFE_ALAW);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_REC656IF >> 2], VPFE_REC656IF);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_CCDCFG >> 2], VPFE_CCDCFG);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_PCR >> 2], VPFE_PCR);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_HD_VD_WID >> 2],
+						VPFE_HD_VD_WID);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_PIX_LINES >> 2],
+						VPFE_PIX_LINES);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_HORZ_INFO >> 2],
+						VPFE_HORZ_INFO);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_VERT_START >> 2],
+						VPFE_VERT_START);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_VERT_LINES >> 2],
+						VPFE_VERT_LINES);
+	vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_HSIZE_OFF >> 2],
+						VPFE_HSIZE_OFF);
+}
+
+static int vpfe_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct vpfe_device *vpfe = platform_get_drvdata(pdev);
+	struct vpfe_ccdc *ccdc = &vpfe->ccdc;
+
+	/* if streaming has not started we don't care */
+	if (!vb2_start_streaming_called(&vpfe->buffer_queue))
+		return 0;
+
+	/* Enable both master and slave clock */
+	pm_runtime_get_sync(dev);
+	vpfe_config_enable(ccdc, 1);
+
+	/* Restore VPFE context */
+	vpfe_restore_context(ccdc);
+
+	vpfe_config_enable(ccdc, 0);
+	pm_runtime_put_sync(dev);
+
+	/* Select default pin state */
+	pinctrl_pm_select_default_state(dev);
+
+	return 0;
+}
+
+#endif
+
+static SIMPLE_DEV_PM_OPS(vpfe_pm_ops, vpfe_suspend, vpfe_resume);
+
+static const struct of_device_id vpfe_of_match[] = {
+	{ .compatible = "ti,am437x-vpfe", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, vpfe_of_match);
+
+static struct platform_driver vpfe_driver = {
+	.probe		= vpfe_probe,
+	.remove		= vpfe_remove,
+	.driver = {
+		.name	= VPFE_MODULE_NAME,
+		.pm	= &vpfe_pm_ops,
+		.of_match_table = of_match_ptr(vpfe_of_match),
+	},
+};
+
+module_platform_driver(vpfe_driver);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("TI AM437x VPFE driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VPFE_VERSION);
diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
new file mode 100644
index 000000000000..0f557352313d
--- /dev/null
+++ b/drivers/media/platform/am437x/am437x-vpfe.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2013 - 2014 Texas Instruments, Inc.
+ *
+ * Benoit Parrot <bparrot@ti.com>
+ * Lad, Prabhakar <prabhakar.csengg@gmail.com>
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef AM437X_VPFE_H
+#define AM437X_VPFE_H
+
+#include <linux/am437x-vpfe.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "am437x-vpfe_regs.h"
+
+enum vpfe_pin_pol {
+	VPFE_PINPOL_POSITIVE = 0,
+	VPFE_PINPOL_NEGATIVE,
+};
+
+enum vpfe_hw_if_type {
+	/* Raw Bayer */
+	VPFE_RAW_BAYER = 0,
+	/* BT656 - 8 bit */
+	VPFE_BT656,
+	/* BT656 - 10 bit */
+	VPFE_BT656_10BIT,
+	/* YCbCr - 8 bit with external sync */
+	VPFE_YCBCR_SYNC_8,
+	/* YCbCr - 16 bit with external sync */
+	VPFE_YCBCR_SYNC_16,
+};
+
+/* interface description */
+struct vpfe_hw_if_param {
+	enum vpfe_hw_if_type if_type;
+	enum vpfe_pin_pol hdpol;
+	enum vpfe_pin_pol vdpol;
+	unsigned int bus_width;
+};
+
+#define VPFE_MAX_SUBDEV		1
+#define VPFE_MAX_INPUTS		1
+
+struct vpfe_pixel_format {
+	struct v4l2_fmtdesc fmtdesc;
+	/* bytes per pixel */
+	int bpp;
+};
+
+struct vpfe_std_info {
+	int active_pixels;
+	int active_lines;
+	/* current frame format */
+	int frame_format;
+};
+
+struct vpfe_route {
+	u32 input;
+	u32 output;
+};
+
+struct vpfe_subdev_info {
+	 char name[32];
+	/* Sub device group id */
+	int grp_id;
+	/* inputs available at the sub device */
+	struct v4l2_input inputs[VPFE_MAX_INPUTS];
+	/* Sub dev routing information for each input */
+	struct vpfe_route *routes;
+	/* check if sub dev supports routing */
+	int can_route;
+	/* ccdc bus/interface configuration */
+	struct vpfe_hw_if_param vpfe_param;
+	struct v4l2_subdev *sd;
+};
+
+struct vpfe_config {
+	/* information about each subdev */
+	struct vpfe_subdev_info sub_devs[VPFE_MAX_SUBDEV];
+	/* Flat array, arranged in groups */
+	struct v4l2_async_subdev *asd[VPFE_MAX_SUBDEV];
+};
+
+struct vpfe_cap_buffer {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
+
+enum ccdc_pixfmt {
+	CCDC_PIXFMT_RAW = 0,
+	CCDC_PIXFMT_YCBCR_16BIT,
+	CCDC_PIXFMT_YCBCR_8BIT,
+};
+
+enum ccdc_frmfmt {
+	CCDC_FRMFMT_PROGRESSIVE = 0,
+	CCDC_FRMFMT_INTERLACED,
+};
+
+/* PIXEL ORDER IN MEMORY from LSB to MSB */
+/* only applicable for 8-bit input mode  */
+enum ccdc_pixorder {
+	CCDC_PIXORDER_YCBYCR,
+	CCDC_PIXORDER_CBYCRY,
+};
+
+enum ccdc_buftype {
+	CCDC_BUFTYPE_FLD_INTERLEAVED,
+	CCDC_BUFTYPE_FLD_SEPARATED
+};
+
+
+/* returns the highest bit used for the gamma */
+static inline u8 ccdc_gamma_width_max_bit(enum vpfe_ccdc_gamma_width width)
+{
+	return 15 - width;
+}
+
+/* returns the highest bit used for this data size */
+static inline u8 ccdc_data_size_max_bit(enum vpfe_ccdc_data_size sz)
+{
+	return sz == VPFE_CCDC_DATA_8BITS ? 7 : 15 - sz;
+}
+
+/* Structure for CCDC configuration parameters for raw capture mode */
+struct ccdc_params_raw {
+	/* pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* progressive or interlaced frame */
+	enum ccdc_frmfmt frm_fmt;
+	struct v4l2_rect win;
+	/* Current Format Bytes Per Pixels */
+	unsigned int bytesperpixel;
+	/* Current Format Bytes per Lines
+	 * (Aligned to 32 bytes) used for HORZ_INFO
+	 */
+	unsigned int bytesperline;
+	/* field id polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* vertical sync polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* horizontal sync polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* interleaved or separated fields */
+	enum ccdc_buftype buf_type;
+	/*
+	 * enable to store the image in inverse
+	 * order in memory(bottom to top)
+	 */
+	unsigned char image_invert_enable;
+	/* configurable parameters */
+	struct vpfe_ccdc_config_params_raw config_params;
+};
+
+struct ccdc_params_ycbcr {
+	/* pixel format */
+	enum ccdc_pixfmt pix_fmt;
+	/* progressive or interlaced frame */
+	enum ccdc_frmfmt frm_fmt;
+	struct v4l2_rect win;
+	/* Current Format Bytes Per Pixels */
+	unsigned int bytesperpixel;
+	/* Current Format Bytes per Lines
+	 * (Aligned to 32 bytes) used for HORZ_INFO
+	 */
+	unsigned int bytesperline;
+	/* field id polarity */
+	enum vpfe_pin_pol fid_pol;
+	/* vertical sync polarity */
+	enum vpfe_pin_pol vd_pol;
+	/* horizontal sync polarity */
+	enum vpfe_pin_pol hd_pol;
+	/* enable BT.656 embedded sync mode */
+	int bt656_enable;
+	/* cb:y:cr:y or y:cb:y:cr in memory */
+	enum ccdc_pixorder pix_order;
+	/* interleaved or separated fields  */
+	enum ccdc_buftype buf_type;
+};
+
+/*
+ * CCDC operational configuration
+ */
+struct ccdc_config {
+	/* CCDC interface type */
+	enum vpfe_hw_if_type if_type;
+	/* Raw Bayer configuration */
+	struct ccdc_params_raw bayer;
+	/* YCbCr configuration */
+	struct ccdc_params_ycbcr ycbcr;
+	/* ccdc base address */
+	void __iomem *base_addr;
+};
+
+struct vpfe_ccdc {
+	struct ccdc_config ccdc_cfg;
+	u32 ccdc_ctx[VPFE_REG_END / sizeof(u32)];
+};
+
+struct vpfe_device {
+	/* V4l2 specific parameters */
+	/* Identifies video device for this channel */
+	struct video_device *video_dev;
+	/* sub devices */
+	struct v4l2_subdev **sd;
+	/* vpfe cfg */
+	struct vpfe_config *cfg;
+	/* V4l2 device */
+	struct v4l2_device v4l2_dev;
+	/* parent device */
+	struct device *pdev;
+	/* subdevice async Notifier */
+	struct v4l2_async_notifier notifier;
+	/* Indicates id of the field which is being displayed */
+	unsigned field;
+	unsigned sequence;
+	/* current interface type */
+	struct vpfe_hw_if_param vpfe_if_params;
+	/* ptr to currently selected sub device */
+	struct vpfe_subdev_info *current_subdev;
+	/* current input at the sub device */
+	int current_input;
+	/* Keeps track of the information about the standard */
+	struct vpfe_std_info std_info;
+	/* std index into std table */
+	int std_index;
+	/* IRQs used when CCDC output to SDRAM */
+	unsigned int irq;
+	/* Pointer pointing to current v4l2_buffer */
+	struct vpfe_cap_buffer *cur_frm;
+	/* Pointer pointing to next v4l2_buffer */
+	struct vpfe_cap_buffer *next_frm;
+	/* Used to store pixel format */
+	struct v4l2_format fmt;
+	/* Used to store current bytes per pixel based on current format */
+	unsigned int bpp;
+	/*
+	 * used when IMP is chained to store the crop window which
+	 * is different from the image window
+	 */
+	struct v4l2_rect crop;
+	/* Buffer queue used in video-buf */
+	struct vb2_queue buffer_queue;
+	/* Allocator-specific contexts for each plane */
+	struct vb2_alloc_ctx *alloc_ctx;
+	/* Queue of filled frames */
+	struct list_head dma_queue;
+	/* IRQ lock for DMA queue */
+	spinlock_t dma_queue_lock;
+	/* lock used to access this structure */
+	struct mutex lock;
+	/*
+	 * offset where second field starts from the starting of the
+	 * buffer for field separated YCbCr formats
+	 */
+	u32 field_off;
+	struct vpfe_ccdc ccdc;
+};
+
+#endif	/* AM437X_VPFE_H */
diff --git a/drivers/media/platform/am437x/am437x-vpfe_regs.h b/drivers/media/platform/am437x/am437x-vpfe_regs.h
new file mode 100644
index 000000000000..4a0ed29723e8
--- /dev/null
+++ b/drivers/media/platform/am437x/am437x-vpfe_regs.h
@@ -0,0 +1,140 @@
+/*
+ * TI AM437x Image Sensor Interface Registers
+ *
+ * Copyright (C) 2013 - 2014 Texas Instruments, Inc.
+ *
+ * Benoit Parrot <bparrot@ti.com>
+ * Lad, Prabhakar <prabhakar.csengg@gmail.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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef AM437X_VPFE_REGS_H
+#define AM437X_VPFE_REGS_H
+
+/* VPFE module register offset */
+#define VPFE_REVISION				0x0
+#define VPFE_PCR				0x4
+#define VPFE_SYNMODE				0x8
+#define VPFE_HD_VD_WID				0xc
+#define VPFE_PIX_LINES				0x10
+#define VPFE_HORZ_INFO				0x14
+#define VPFE_VERT_START				0x18
+#define VPFE_VERT_LINES				0x1c
+#define VPFE_CULLING				0x20
+#define VPFE_HSIZE_OFF				0x24
+#define VPFE_SDOFST				0x28
+#define VPFE_SDR_ADDR				0x2c
+#define VPFE_CLAMP				0x30
+#define VPFE_DCSUB				0x34
+#define VPFE_COLPTN				0x38
+#define VPFE_BLKCMP				0x3c
+#define VPFE_VDINT				0x48
+#define VPFE_ALAW				0x4c
+#define VPFE_REC656IF				0x50
+#define VPFE_CCDCFG				0x54
+#define VPFE_DMA_CNTL				0x98
+#define VPFE_SYSCONFIG				0x104
+#define VPFE_CONFIG				0x108
+#define VPFE_IRQ_EOI				0x110
+#define VPFE_IRQ_STS_RAW			0x114
+#define VPFE_IRQ_STS				0x118
+#define VPFE_IRQ_EN_SET				0x11c
+#define VPFE_IRQ_EN_CLR				0x120
+#define VPFE_REG_END				0x124
+
+/* Define bit fields within selected registers */
+#define VPFE_FID_POL_MASK			1
+#define VPFE_FID_POL_SHIFT			4
+#define VPFE_HD_POL_MASK			1
+#define VPFE_HD_POL_SHIFT			3
+#define VPFE_VD_POL_MASK			1
+#define VPFE_VD_POL_SHIFT			2
+#define VPFE_HSIZE_OFF_MASK			0xffffffe0
+#define VPFE_32BYTE_ALIGN_VAL			31
+#define VPFE_FRM_FMT_MASK			0x1
+#define VPFE_FRM_FMT_SHIFT			7
+#define VPFE_DATA_SZ_MASK			7
+#define VPFE_DATA_SZ_SHIFT			8
+#define VPFE_PIX_FMT_MASK			3
+#define VPFE_PIX_FMT_SHIFT			12
+#define VPFE_VP2SDR_DISABLE			0xfffbffff
+#define VPFE_WEN_ENABLE				(1 << 17)
+#define VPFE_SDR2RSZ_DISABLE			0xfff7ffff
+#define VPFE_VDHDEN_ENABLE			(1 << 16)
+#define VPFE_LPF_ENABLE				(1 << 14)
+#define VPFE_ALAW_ENABLE			(1 << 3)
+#define VPFE_ALAW_GAMMA_WD_MASK			7
+#define VPFE_BLK_CLAMP_ENABLE			(1 << 31)
+#define VPFE_BLK_SGAIN_MASK			0x1f
+#define VPFE_BLK_ST_PXL_MASK			0x7fff
+#define VPFE_BLK_ST_PXL_SHIFT			10
+#define VPFE_BLK_SAMPLE_LN_MASK			7
+#define VPFE_BLK_SAMPLE_LN_SHIFT		28
+#define VPFE_BLK_SAMPLE_LINE_MASK		7
+#define VPFE_BLK_SAMPLE_LINE_SHIFT		25
+#define VPFE_BLK_DC_SUB_MASK			0x03fff
+#define VPFE_BLK_COMP_MASK			0xff
+#define VPFE_BLK_COMP_GB_COMP_SHIFT		8
+#define VPFE_BLK_COMP_GR_COMP_SHIFT		16
+#define VPFE_BLK_COMP_R_COMP_SHIFT		24
+#define VPFE_LATCH_ON_VSYNC_DISABLE		(1 << 15)
+#define VPFE_DATA_PACK_ENABLE			(1 << 11)
+#define VPFE_HORZ_INFO_SPH_SHIFT		16
+#define VPFE_VERT_START_SLV0_SHIFT		16
+#define VPFE_VDINT_VDINT0_SHIFT			16
+#define VPFE_VDINT_VDINT1_MASK			0xffff
+#define VPFE_PPC_RAW				1
+#define VPFE_DCSUB_DEFAULT_VAL			0
+#define VPFE_CLAMP_DEFAULT_VAL			0
+#define VPFE_COLPTN_VAL				0xbb11bb11
+#define VPFE_TWO_BYTES_PER_PIXEL		2
+#define VPFE_INTERLACED_IMAGE_INVERT		0x4b6d
+#define VPFE_INTERLACED_NO_IMAGE_INVERT		0x0249
+#define VPFE_PROGRESSIVE_IMAGE_INVERT		0x4000
+#define VPFE_PROGRESSIVE_NO_IMAGE_INVERT	0
+#define VPFE_INTERLACED_HEIGHT_SHIFT		1
+#define VPFE_SYN_MODE_INPMOD_SHIFT		12
+#define VPFE_SYN_MODE_INPMOD_MASK		3
+#define VPFE_SYN_MODE_8BITS			(7 << 8)
+#define VPFE_SYN_MODE_10BITS			(6 << 8)
+#define VPFE_SYN_MODE_11BITS			(5 << 8)
+#define VPFE_SYN_MODE_12BITS			(4 << 8)
+#define VPFE_SYN_MODE_13BITS			(3 << 8)
+#define VPFE_SYN_MODE_14BITS			(2 << 8)
+#define VPFE_SYN_MODE_15BITS			(1 << 8)
+#define VPFE_SYN_MODE_16BITS			(0 << 8)
+#define VPFE_SYN_FLDMODE_MASK			1
+#define VPFE_SYN_FLDMODE_SHIFT			7
+#define VPFE_REC656IF_BT656_EN			3
+#define VPFE_SYN_MODE_VD_POL_NEGATIVE		(1 << 2)
+#define VPFE_CCDCFG_Y8POS_SHIFT			11
+#define VPFE_CCDCFG_BW656_10BIT			(1 << 5)
+#define VPFE_SDOFST_FIELD_INTERLEAVED		0x249
+#define VPFE_NO_CULLING				0xffff00ff
+#define VPFE_VDINT0				(1 << 0)
+#define VPFE_VDINT1				(1 << 1)
+#define VPFE_VDINT2				(1 << 2)
+#define VPFE_DMA_CNTL_OVERFLOW			(1 << 31)
+
+#define VPFE_CONFIG_PCLK_INV_SHIFT		0
+#define VPFE_CONFIG_PCLK_INV_MASK		1
+#define VPFE_CONFIG_PCLK_INV_NOT_INV		0
+#define VPFE_CONFIG_PCLK_INV_INV		1
+#define VPFE_CONFIG_EN_SHIFT			1
+#define VPFE_CONFIG_EN_MASK			2
+#define VPFE_CONFIG_EN_DISABLE			0
+#define VPFE_CONFIG_EN_ENABLE			1
+#define VPFE_CONFIG_ST_SHIFT			2
+#define VPFE_CONFIG_ST_MASK			4
+#define VPFE_CONFIG_ST_OCP_ACTIVE		0
+#define VPFE_CONFIG_ST_OCP_STANDBY		1
+
+#endif		/* AM437X_VPFE_REGS_H */
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index b4029ae293d3..856b542b35b9 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -718,6 +718,7 @@ static int coda_start_encoding(struct coda_ctx *ctx)
 	struct vb2_buffer *buf;
 	int gamma, ret, value;
 	u32 dst_fourcc;
+	int num_fb;
 	u32 stride;
 
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
@@ -983,12 +984,14 @@ static int coda_start_encoding(struct coda_ctx *ctx)
 			v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
 			goto out;
 		}
+		num_fb = 2;
 		stride = q_data_src->bytesperline;
 	} else {
 		ctx->num_internal_frames = 0;
+		num_fb = 0;
 		stride = 0;
 	}
-	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
+	coda_write(dev, num_fb, CODA_CMD_SET_FRAME_BUF_NUM);
 	coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE);
 
 	if (dev->devtype->product == CODA_7541) {
@@ -1316,8 +1319,10 @@ static void coda_seq_end_work(struct work_struct *work)
 
 static void coda_bit_release(struct coda_ctx *ctx)
 {
+	mutex_lock(&ctx->buffer_mutex);
 	coda_free_framebuffers(ctx);
 	coda_free_context_buffers(ctx);
+	mutex_unlock(&ctx->buffer_mutex);
 }
 
 const struct coda_context_ops coda_bit_encode_ops = {
@@ -1431,9 +1436,10 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
 		height = val & CODA7_PICHEIGHT_MASK;
 	}
 
-	if (width > q_data_dst->width || height > q_data_dst->height) {
+	if (width > q_data_dst->bytesperline || height > q_data_dst->height) {
 		v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n",
-			 width, height, q_data_dst->width, q_data_dst->height);
+			 width, height, q_data_dst->bytesperline,
+			 q_data_dst->height);
 		return -EINVAL;
 	}
 
@@ -1565,6 +1571,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 	struct vb2_buffer *dst_buf;
 	struct coda_dev *dev = ctx->dev;
 	struct coda_q_data *q_data_dst;
+	struct coda_buffer_meta *meta;
 	u32 reg_addr, reg_stride;
 
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -1643,12 +1650,12 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 		coda_write(dev, ctx->iram_info.axi_sram_use,
 				CODA7_REG_BIT_AXI_SRAM_USE);
 
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
-		struct coda_buffer_meta *meta;
+	meta = list_first_entry_or_null(&ctx->buffer_meta_list,
+					struct coda_buffer_meta, list);
+
+	if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
 
 		/* If this is the last buffer in the bitstream, add padding */
-		meta = list_first_entry(&ctx->buffer_meta_list,
-				      struct coda_buffer_meta, list);
 		if (meta->end == (ctx->bitstream_fifo.kfifo.in &
 				  ctx->bitstream_fifo.kfifo.mask)) {
 			static unsigned char buf[512];
@@ -1665,6 +1672,9 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 
 	coda_kfifo_sync_to_device_full(ctx);
 
+	/* Clear decode success flag */
+	coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS);
+
 	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
 
 	return 0;
@@ -1821,6 +1831,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 			memset(&ctx->frame_metas[decoded_idx], 0,
 			       sizeof(struct coda_buffer_meta));
 			ctx->frame_metas[decoded_idx].sequence = val;
+			ctx->sequence_offset++;
 		}
 		mutex_unlock(&ctx->bitstream_mutex);
 
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 39330a70f752..6f32e6d6b156 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -37,6 +37,7 @@
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-vmalloc.h>
 
 #include "coda.h"
 
@@ -180,6 +181,7 @@ struct coda_video_device {
 	const char *name;
 	enum coda_inst_type type;
 	const struct coda_context_ops *ops;
+	bool direct;
 	u32 src_formats[CODA_MAX_FORMATS];
 	u32 dst_formats[CODA_MAX_FORMATS];
 };
@@ -468,6 +470,18 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
 	return 0;
 }
 
+static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
+					    u32 width, u32 height)
+{
+	/*
+	 * This is a rough estimate for sensible compressed buffer
+	 * sizes (between 1 and 16 bits per pixel). This could be
+	 * improved by better format specific worst case estimates.
+	 */
+	return round_up(clamp(sizeimage, width * height / 8,
+					 width * height * 2), PAGE_SIZE);
+}
+
 static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
 			struct v4l2_format *f)
 {
@@ -513,15 +527,10 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
 	case V4L2_PIX_FMT_H264:
 	case V4L2_PIX_FMT_MPEG4:
 		f->fmt.pix.bytesperline = 0;
-		/*
-		 * This is a rough estimate for sensible compressed buffer
-		 * sizes (between 1 and 16 bits per pixel). This could be
-		 * improved by better format specific worst case estimates.
-		 */
-		f->fmt.pix.sizeimage = round_up(clamp(f->fmt.pix.sizeimage,
-				f->fmt.pix.width * f->fmt.pix.height / 8,
-				f->fmt.pix.width * f->fmt.pix.height * 2),
-				PAGE_SIZE);
+		f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx,
+							f->fmt.pix.sizeimage,
+							f->fmt.pix.width,
+							f->fmt.pix.height);
 		break;
 	default:
 		BUG();
@@ -592,7 +601,11 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv,
 	if (ret < 0)
 		return ret;
 
-	if (!f->fmt.pix.colorspace) {
+	switch (f->fmt.pix.colorspace) {
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_JPEG:
+		break;
+	default:
 		if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
 			f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
 		else
@@ -670,6 +683,7 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv,
 
 	ctx->colorspace = f->fmt.pix.colorspace;
 
+	memset(&f_cap, 0, sizeof(f_cap));
 	f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	coda_g_fmt(file, priv, &f_cap);
 	f_cap.fmt.pix.width = f->fmt.pix.width;
@@ -908,7 +922,8 @@ static void coda_pic_run_work(struct work_struct *work)
 		ctx->ops->finish_run(ctx);
 	}
 
-	if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out))
+	if ((ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) &&
+	    ctx->ops->seq_end_work)
 		queue_work(dev->workqueue, &ctx->seq_end_work);
 
 	mutex_unlock(&dev->coda_mutex);
@@ -939,15 +954,43 @@ static int coda_job_ready(void *m2m_priv)
 		return 0;
 	}
 
-	if (ctx->hold ||
-	    ((ctx->inst_type == CODA_INST_DECODER) &&
-	     !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
-	     (coda_get_bitstream_payload(ctx) < 512) &&
-	     !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
-		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
-			 "%d: not ready: not enough bitstream data.\n",
-			 ctx->idx);
-		return 0;
+	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
+		struct list_head *meta;
+		bool stream_end;
+		int num_metas;
+		int src_bufs;
+
+		if (ctx->hold && !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) {
+			v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+				 "%d: not ready: on hold for more buffers.\n",
+				 ctx->idx);
+			return 0;
+		}
+
+		stream_end = ctx->bit_stream_param &
+			     CODA_BIT_STREAM_END_FLAG;
+
+		num_metas = 0;
+		list_for_each(meta, &ctx->buffer_meta_list)
+			num_metas++;
+
+		src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx);
+
+		if (!stream_end && (num_metas + src_bufs) < 2) {
+			v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+				 "%d: not ready: need 2 buffers available (%d, %d)\n",
+				 ctx->idx, num_metas, src_bufs);
+			return 0;
+		}
+
+
+		if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
+		    !stream_end && (coda_get_bitstream_payload(ctx) < 512)) {
+			v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+				 "%d: not ready: not enough bitstream data (%d).\n",
+				 ctx->idx, coda_get_bitstream_payload(ctx));
+			return 0;
+		}
 	}
 
 	if (ctx->aborting) {
@@ -1023,13 +1066,14 @@ static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type)
 
 static void set_default_params(struct coda_ctx *ctx)
 {
-	unsigned int max_w, max_h, size;
+	unsigned int max_w, max_h, usize, csize;
 
 	ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
 				     ctx->cvd->dst_formats[0]);
 	max_w = min(ctx->codec->max_w, 1920U);
 	max_h = min(ctx->codec->max_h, 1088U);
-	size = max_w * max_h * 3 / 2;
+	usize = max_w * max_h * 3 / 2;
+	csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h);
 
 	ctx->params.codec_mode = ctx->codec->mode;
 	ctx->colorspace = V4L2_COLORSPACE_REC709;
@@ -1044,14 +1088,14 @@ static void set_default_params(struct coda_ctx *ctx)
 	ctx->q_data[V4L2_M2M_DST].height = max_h;
 	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) {
 		ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
-		ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
+		ctx->q_data[V4L2_M2M_SRC].sizeimage = usize;
 		ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
-		ctx->q_data[V4L2_M2M_DST].sizeimage = round_up(size, PAGE_SIZE);
+		ctx->q_data[V4L2_M2M_DST].sizeimage = csize;
 	} else {
 		ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
-		ctx->q_data[V4L2_M2M_SRC].sizeimage = round_up(size, PAGE_SIZE);
+		ctx->q_data[V4L2_M2M_SRC].sizeimage = csize;
 		ctx->q_data[V4L2_M2M_DST].bytesperline = max_w;
-		ctx->q_data[V4L2_M2M_DST].sizeimage = size;
+		ctx->q_data[V4L2_M2M_DST].sizeimage = usize;
 	}
 	ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
 	ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
@@ -1080,6 +1124,7 @@ static int coda_queue_setup(struct vb2_queue *vq,
 	*nplanes = 1;
 	sizes[0] = size;
 
+	/* Set to vb2-dma-contig allocator context, ignored by vb2-vmalloc */
 	alloc_ctxs[0] = ctx->dev->alloc_ctx;
 
 	v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
@@ -1109,6 +1154,7 @@ static int coda_buf_prepare(struct vb2_buffer *vb)
 static void coda_buf_queue(struct vb2_buffer *vb)
 {
 	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_queue *vq = vb->vb2_queue;
 	struct coda_q_data *q_data;
 
 	q_data = get_q_data(ctx, vb->vb2_queue->type);
@@ -1117,8 +1163,7 @@ static void coda_buf_queue(struct vb2_buffer *vb)
 	 * In the decoder case, immediately try to copy the buffer into the
 	 * bitstream ringbuffer and mark it as ready to be dequeued.
 	 */
-	if (ctx->inst_type == CODA_INST_DECODER &&
-	    vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+	if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
 		/*
 		 * For backwards compatibility, queuing an empty buffer marks
 		 * the stream end
@@ -1218,7 +1263,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 		return 0;
 
 	/* Allow BIT decoder device_run with no new buffers queued */
-	if (ctx->inst_type == CODA_INST_DECODER)
+	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
 		v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
 
 	ctx->gopcounter = ctx->params.gop_size - 1;
@@ -1271,7 +1316,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
 
 		coda_bit_stream_end_flag(ctx);
 
-		ctx->isequence = 0;
+		ctx->qsequence = 0;
 
 		while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
 			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
@@ -1290,6 +1335,10 @@ static void coda_stop_streaming(struct vb2_queue *q)
 	if (!ctx->streamon_out && !ctx->streamon_cap) {
 		struct coda_buffer_meta *meta;
 
+		if (ctx->ops->seq_end_work) {
+			queue_work(dev->workqueue, &ctx->seq_end_work);
+			flush_work(&ctx->seq_end_work);
+		}
 		mutex_lock(&ctx->bitstream_mutex);
 		while (!list_empty(&ctx->buffer_meta_list)) {
 			meta = list_first_entry(&ctx->buffer_meta_list,
@@ -1300,6 +1349,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
 		mutex_unlock(&ctx->bitstream_mutex);
 		kfifo_init(&ctx->bitstream_fifo,
 			ctx->bitstream.vaddr, ctx->bitstream.size);
+		ctx->initialized = 0;
 		ctx->runcounter = 0;
 		ctx->aborting = 0;
 	}
@@ -1521,8 +1571,8 @@ int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
 	int ret;
 
 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-	src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
-	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	src_vq->mem_ops = &vb2_vmalloc_memops;
 
 	ret = coda_queue_init(priv, src_vq);
 	if (ret)
@@ -1577,9 +1627,11 @@ static int coda_open(struct file *file)
 	ctx->cvd = to_coda_video_device(vdev);
 	ctx->inst_type = ctx->cvd->type;
 	ctx->ops = ctx->cvd->ops;
+	ctx->use_bit = !ctx->cvd->direct;
 	init_completion(&ctx->completion);
 	INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
-	INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
+	if (ctx->ops->seq_end_work)
+		INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
 	v4l2_fh_init(&ctx->fh, video_devdata(file));
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
@@ -1630,22 +1682,25 @@ static int coda_open(struct file *file)
 
 	ctx->fh.ctrl_handler = &ctx->ctrls;
 
-	ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
-				     CODA_PARA_BUF_SIZE, "parabuf");
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
-		goto err_dma_alloc;
+	if (ctx->use_bit) {
+		ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
+					     CODA_PARA_BUF_SIZE, "parabuf");
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
+			goto err_dma_alloc;
+		}
 	}
-
-	ctx->bitstream.size = CODA_MAX_FRAME_SIZE;
-	ctx->bitstream.vaddr = dma_alloc_writecombine(
-			&dev->plat_dev->dev, ctx->bitstream.size,
-			&ctx->bitstream.paddr, GFP_KERNEL);
-	if (!ctx->bitstream.vaddr) {
-		v4l2_err(&dev->v4l2_dev,
-			 "failed to allocate bitstream ringbuffer");
-		ret = -ENOMEM;
-		goto err_dma_writecombine;
+	if (ctx->use_bit && ctx->inst_type == CODA_INST_DECODER) {
+		ctx->bitstream.size = CODA_MAX_FRAME_SIZE;
+		ctx->bitstream.vaddr = dma_alloc_writecombine(
+				&dev->plat_dev->dev, ctx->bitstream.size,
+				&ctx->bitstream.paddr, GFP_KERNEL);
+		if (!ctx->bitstream.vaddr) {
+			v4l2_err(&dev->v4l2_dev,
+				 "failed to allocate bitstream ringbuffer");
+			ret = -ENOMEM;
+			goto err_dma_writecombine;
+		}
 	}
 	kfifo_init(&ctx->bitstream_fifo,
 		ctx->bitstream.vaddr, ctx->bitstream.size);
@@ -1693,16 +1748,14 @@ static int coda_release(struct file *file)
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
 		 ctx);
 
-	debugfs_remove_recursive(ctx->debugfs_entry);
-
-	if (ctx->inst_type == CODA_INST_DECODER)
+	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
 		coda_bit_stream_end_flag(ctx);
 
 	/* If this instance is running, call .job_abort and wait for it to end */
 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 
 	/* In case the instance was not running, we still need to call SEQ_END */
-	if (ctx->initialized) {
+	if (ctx->initialized && ctx->ops->seq_end_work) {
 		queue_work(dev->workqueue, &ctx->seq_end_work);
 		flush_work(&ctx->seq_end_work);
 	}
@@ -1728,6 +1781,7 @@ static int coda_release(struct file *file)
 	clear_bit(ctx->idx, &dev->instance_mask);
 	if (ctx->ops->release)
 		ctx->ops->release(ctx);
+	debugfs_remove_recursive(ctx->debugfs_entry);
 	kfree(ctx);
 
 	return 0;
@@ -1844,10 +1898,11 @@ static int coda_register_device(struct coda_dev *dev, int i)
 {
 	struct video_device *vfd = &dev->vfd[i];
 
-	if (i > ARRAY_SIZE(dev->vfd))
+	if (i >= dev->devtype->num_vdevs)
 		return -EINVAL;
 
-	snprintf(vfd->name, sizeof(vfd->name), dev->devtype->vdevs[i]->name);
+	snprintf(vfd->name, sizeof(vfd->name), "%s",
+		 dev->devtype->vdevs[i]->name);
 	vfd->fops	= &coda_fops;
 	vfd->ioctl_ops	= &coda_ioctl_ops;
 	vfd->release	= video_device_release_empty,
@@ -2001,7 +2056,6 @@ static const struct coda_devtype coda_devdata[] = {
 
 static struct platform_device_id coda_platform_ids[] = {
 	{ .name = "coda-imx27", .driver_data = CODA_IMX27 },
-	{ .name = "coda-imx53", .driver_data = CODA_IMX53 },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(platform, coda_platform_ids);
@@ -2142,6 +2196,7 @@ static int coda_probe(struct platform_device *pdev)
 	if (!dev->iram.vaddr) {
 		dev_warn(&pdev->dev, "unable to alloc iram\n");
 	} else {
+		memset(dev->iram.vaddr, 0, dev->iram.size);
 		dev->iram.blob.data = dev->iram.vaddr;
 		dev->iram.blob.size = dev->iram.size;
 		dev->iram.dentry = debugfs_create_blob("iram", 0644,
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 5dd47e5f97c1..0c35cd5032ff 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -198,7 +198,6 @@ struct coda_ctx {
 	int				initialized;
 	int				streamon_out;
 	int				streamon_cap;
-	u32				isequence;
 	u32				qsequence;
 	u32				osequence;
 	u32				sequence_offset;
@@ -236,6 +235,7 @@ struct coda_ctx {
 	u32				frame_mem_ctrl;
 	int				display_idx;
 	struct dentry			*debugfs_entry;
+	bool				use_bit;
 };
 
 extern int coda_debug;
diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h
index 8e015b8aa8fa..7d026241171b 100644
--- a/drivers/media/platform/coda/coda_regs.h
+++ b/drivers/media/platform/coda/coda_regs.h
@@ -304,9 +304,9 @@
 #define		CODA_RATECONTROL_AUTOSKIP_OFFSET		31
 #define		CODA_RATECONTROL_AUTOSKIP_MASK			0x01
 #define		CODA_RATECONTROL_INITIALDELAY_OFFSET		16
-#define		CODA_RATECONTROL_INITIALDELAY_MASK		0x7f
+#define		CODA_RATECONTROL_INITIALDELAY_MASK		0x7fff
 #define		CODA_RATECONTROL_BITRATE_OFFSET		1
-#define		CODA_RATECONTROL_BITRATE_MASK			0x7f
+#define		CODA_RATECONTROL_BITRATE_MASK			0x7fff
 #define		CODA_RATECONTROL_ENABLE_OFFSET			0
 #define		CODA_RATECONTROL_ENABLE_MASK			0x01
 #define CODA_CMD_ENC_SEQ_RC_BUF_SIZE				0x1b0
diff --git a/drivers/media/platform/davinci/Kconfig b/drivers/media/platform/davinci/Kconfig
index d9e1ddb586b1..469e9d28cec0 100644
--- a/drivers/media/platform/davinci/Kconfig
+++ b/drivers/media/platform/davinci/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_DAVINCI_VPIF_DISPLAY
 	tristate "TI DaVinci VPIF V4L2-Display driver"
-	depends on VIDEO_DEV
+	depends on VIDEO_V4L2
 	depends on ARCH_DAVINCI || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
@@ -16,7 +16,7 @@ config VIDEO_DAVINCI_VPIF_DISPLAY
 
 config VIDEO_DAVINCI_VPIF_CAPTURE
 	tristate "TI DaVinci VPIF video capture driver"
-	depends on VIDEO_DEV
+	depends on VIDEO_V4L2
 	depends on ARCH_DAVINCI || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
@@ -75,7 +75,7 @@ config VIDEO_DM365_ISIF
 
 config VIDEO_DAVINCI_VPBE_DISPLAY
 	tristate "TI DaVinci VPBE V4L2-Display driver"
-	depends on ARCH_DAVINCI
+	depends on VIDEO_V4L2 && ARCH_DAVINCI
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	help
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index 0abdb17fb19c..fa572aacdb3f 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -466,18 +466,6 @@ static inline void gsc_hw_clear_irq(struct gsc_dev *dev, int irq)
 	writel(cfg, dev->regs + GSC_IRQ);
 }
 
-static inline void gsc_lock(struct vb2_queue *vq)
-{
-	struct gsc_ctx *ctx = vb2_get_drv_priv(vq);
-	mutex_lock(&ctx->gsc_dev->lock);
-}
-
-static inline void gsc_unlock(struct vb2_queue *vq)
-{
-	struct gsc_ctx *ctx = vb2_get_drv_priv(vq);
-	mutex_unlock(&ctx->gsc_dev->lock);
-}
-
 static inline bool gsc_ctx_state_is_set(u32 mask, struct gsc_ctx *ctx)
 {
 	unsigned long flags;
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index 74e1de637e8f..d5cffef2e227 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -267,8 +267,8 @@ static struct vb2_ops gsc_m2m_qops = {
 	.queue_setup	 = gsc_m2m_queue_setup,
 	.buf_prepare	 = gsc_m2m_buf_prepare,
 	.buf_queue	 = gsc_m2m_buf_queue,
-	.wait_prepare	 = gsc_unlock,
-	.wait_finish	 = gsc_lock,
+	.wait_prepare	 = vb2_ops_wait_prepare,
+	.wait_finish	 = vb2_ops_wait_finish,
 	.stop_streaming	 = gsc_m2m_stop_streaming,
 	.start_streaming = gsc_m2m_start_streaming,
 };
@@ -590,6 +590,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
 	src_vq->mem_ops = &vb2_dma_contig_memops;
 	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &ctx->gsc_dev->lock;
 
 	ret = vb2_queue_init(src_vq);
 	if (ret)
@@ -603,6 +604,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
 	dst_vq->mem_ops = &vb2_dma_contig_memops;
 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &ctx->gsc_dev->lock;
 
 	return vb2_queue_init(dst_vq);
 }
diff --git a/drivers/media/platform/marvell-ccic/Kconfig b/drivers/media/platform/marvell-ccic/Kconfig
index 6265d36adceb..4bf5bd1e90d6 100644
--- a/drivers/media/platform/marvell-ccic/Kconfig
+++ b/drivers/media/platform/marvell-ccic/Kconfig
@@ -5,6 +5,7 @@ config VIDEO_CAFE_CCIC
 	select VIDEO_OV7670
 	select VIDEOBUF2_VMALLOC
 	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_DMA_SG
 	---help---
 	  This is a video4linux2 driver for the Marvell 88ALP01 integrated
 	  CMOS camera controller.  This is the controller found on first-
@@ -13,7 +14,7 @@ config VIDEO_CAFE_CCIC
 config VIDEO_MMP_CAMERA
 	tristate "Marvell Armada 610 integrated camera controller support"
 	depends on ARCH_MMP && I2C && VIDEO_V4L2
-	depends on HAS_DMA
+	depends on HAS_DMA && BROKEN
 	select VIDEO_OV7670
 	select I2C_GPIO
 	select VIDEOBUF2_DMA_SG
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 193373ff268d..dd5b1415f974 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1913,7 +1913,6 @@ int mccic_register(struct mcam_camera *cam)
 
 	mutex_lock(&cam->s_mutex);
 	cam->vdev = mcam_v4l_template;
-	cam->vdev.debug = 0;
 	cam->vdev.v4l2_dev = &cam->v4l2_dev;
 	video_set_drvdata(&cam->vdev, cam);
 	ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 51c2129bdcc6..deca80903c3a 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -220,6 +220,9 @@ static u32 isp_xclk_calc_divider(unsigned long *rate, unsigned long parent_rate)
 		return ISPTCTRL_CTRL_DIV_BYPASS;
 	}
 
+	if (*rate == 0)
+		*rate = 1;
+
 	divider = DIV_ROUND_CLOSEST(parent_rate, *rate);
 	if (divider >= ISPTCTRL_CTRL_DIV_BYPASS)
 		divider = ISPTCTRL_CTRL_DIV_BYPASS - 1;
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index aa40c8269ab8..54479d60cc0d 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -536,24 +536,12 @@ static void buffer_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&camif->slock, flags);
 }
 
-static void camif_lock(struct vb2_queue *vq)
-{
-	struct camif_vp *vp = vb2_get_drv_priv(vq);
-	mutex_lock(&vp->camif->lock);
-}
-
-static void camif_unlock(struct vb2_queue *vq)
-{
-	struct camif_vp *vp = vb2_get_drv_priv(vq);
-	mutex_unlock(&vp->camif->lock);
-}
-
 static const struct vb2_ops s3c_camif_qops = {
 	.queue_setup	 = queue_setup,
 	.buf_prepare	 = buffer_prepare,
 	.buf_queue	 = buffer_queue,
-	.wait_prepare	 = camif_unlock,
-	.wait_finish	 = camif_lock,
+	.wait_prepare	 = vb2_ops_wait_prepare,
+	.wait_finish	 = vb2_ops_wait_finish,
 	.start_streaming = start_streaming,
 	.stop_streaming	 = stop_streaming,
 };
@@ -1161,6 +1149,7 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
 	q->buf_struct_size = sizeof(struct camif_buffer);
 	q->drv_priv = vp;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &vp->camif->lock;
 
 	ret = vb2_queue_init(q);
 	if (ret)
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 47ba8fbb0426..ec3e1248923d 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/version.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index fbfdf03b9054..8e44a59d8ec2 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -810,6 +810,7 @@ static int s5p_mfc_open(struct file *file)
 	q = &ctx->vq_dst;
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	q->drv_priv = &ctx->fh;
+	q->lock = &dev->mfc_mutex;
 	if (vdev == dev->vfd_dec) {
 		q->io_modes = VB2_MMAP;
 		q->ops = get_dec_queue_ops();
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index c6c3452ccca1..aebe4fd7f03a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -18,7 +18,6 @@
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
@@ -813,7 +812,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv,
 	unsigned long flags;
 
 	switch (cmd->cmd) {
-	case V4L2_ENC_CMD_STOP:
+	case V4L2_DEC_CMD_STOP:
 		if (cmd->flags != 0)
 			return -EINVAL;
 
@@ -944,22 +943,6 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 	return 0;
 }
 
-static void s5p_mfc_unlock(struct vb2_queue *q)
-{
-	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-	struct s5p_mfc_dev *dev = ctx->dev;
-
-	mutex_unlock(&dev->mfc_mutex);
-}
-
-static void s5p_mfc_lock(struct vb2_queue *q)
-{
-	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-	struct s5p_mfc_dev *dev = ctx->dev;
-
-	mutex_lock(&dev->mfc_mutex);
-}
-
 static int s5p_mfc_buf_init(struct vb2_buffer *vb)
 {
 	struct vb2_queue *vq = vb->vb2_queue;
@@ -1107,8 +1090,8 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
 
 static struct vb2_ops s5p_mfc_dec_qops = {
 	.queue_setup		= s5p_mfc_queue_setup,
-	.wait_prepare		= s5p_mfc_unlock,
-	.wait_finish		= s5p_mfc_lock,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
 	.buf_init		= s5p_mfc_buf_init,
 	.start_streaming	= s5p_mfc_start_streaming,
 	.stop_streaming		= s5p_mfc_stop_streaming,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index bd64f1dcbdb5..e65993f4b901 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
-#include <linux/version.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
@@ -1867,22 +1866,6 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 	return 0;
 }
 
-static void s5p_mfc_unlock(struct vb2_queue *q)
-{
-	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-	struct s5p_mfc_dev *dev = ctx->dev;
-
-	mutex_unlock(&dev->mfc_mutex);
-}
-
-static void s5p_mfc_lock(struct vb2_queue *q)
-{
-	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-	struct s5p_mfc_dev *dev = ctx->dev;
-
-	mutex_lock(&dev->mfc_mutex);
-}
-
 static int s5p_mfc_buf_init(struct vb2_buffer *vb)
 {
 	struct vb2_queue *vq = vb->vb2_queue;
@@ -2052,8 +2035,8 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
 
 static struct vb2_ops s5p_mfc_enc_qops = {
 	.queue_setup		= s5p_mfc_queue_setup,
-	.wait_prepare		= s5p_mfc_unlock,
-	.wait_finish		= s5p_mfc_lock,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
 	.buf_init		= s5p_mfc_buf_init,
 	.buf_prepare		= s5p_mfc_buf_prepare,
 	.start_streaming	= s5p_mfc_start_streaming,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 9aea179943ce..d826c58b5d53 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -1340,11 +1340,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
 	/* 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) {
+	if (ctx->display_delay_enable) {
 		reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
 		writel(ctx->display_delay, mfc_regs->d_display_delay);
 	}
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index b4d2696501e4..72d4f2e1efc0 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -926,22 +926,6 @@ static void buf_queue(struct vb2_buffer *vb)
 	mxr_dbg(mdev, "queuing buffer\n");
 }
 
-static void wait_lock(struct vb2_queue *vq)
-{
-	struct mxr_layer *layer = vb2_get_drv_priv(vq);
-
-	mxr_dbg(layer->mdev, "%s\n", __func__);
-	mutex_lock(&layer->mutex);
-}
-
-static void wait_unlock(struct vb2_queue *vq)
-{
-	struct mxr_layer *layer = vb2_get_drv_priv(vq);
-
-	mxr_dbg(layer->mdev, "%s\n", __func__);
-	mutex_unlock(&layer->mutex);
-}
-
 static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct mxr_layer *layer = vb2_get_drv_priv(vq);
@@ -1040,8 +1024,8 @@ static void stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops mxr_video_qops = {
 	.queue_setup = queue_setup,
 	.buf_queue = buf_queue,
-	.wait_prepare = wait_unlock,
-	.wait_finish = wait_lock,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
 	.start_streaming = start_streaming,
 	.stop_streaming = stop_streaming,
 };
@@ -1122,6 +1106,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
 		.ops = &mxr_video_qops,
 		.min_buffers_needed = 1,
 		.mem_ops = &vb2_dma_contig_memops,
+		.lock = &layer->mutex,
 	};
 
 	return layer;
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index aaa1f6f25a29..a901b6248557 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -242,20 +242,6 @@ static void sh_veu_job_abort(void *priv)
 	veu->aborting = true;
 }
 
-static void sh_veu_lock(void *priv)
-{
-	struct sh_veu_dev *veu = priv;
-
-	mutex_lock(&veu->fop_lock);
-}
-
-static void sh_veu_unlock(void *priv)
-{
-	struct sh_veu_dev *veu = priv;
-
-	mutex_unlock(&veu->fop_lock);
-}
-
 static void sh_veu_process(struct sh_veu_dev *veu,
 			   struct vb2_buffer *src_buf,
 			   struct vb2_buffer *dst_buf)
@@ -950,36 +936,28 @@ static void sh_veu_buf_queue(struct vb2_buffer *vb)
 	v4l2_m2m_buf_queue(veu->m2m_ctx, vb);
 }
 
-static void sh_veu_wait_prepare(struct vb2_queue *q)
-{
-	sh_veu_unlock(vb2_get_drv_priv(q));
-}
-
-static void sh_veu_wait_finish(struct vb2_queue *q)
-{
-	sh_veu_lock(vb2_get_drv_priv(q));
-}
-
 static const struct vb2_ops sh_veu_qops = {
 	.queue_setup	 = sh_veu_queue_setup,
 	.buf_prepare	 = sh_veu_buf_prepare,
 	.buf_queue	 = sh_veu_buf_queue,
-	.wait_prepare	 = sh_veu_wait_prepare,
-	.wait_finish	 = sh_veu_wait_finish,
+	.wait_prepare	 = vb2_ops_wait_prepare,
+	.wait_finish	 = vb2_ops_wait_finish,
 };
 
 static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
 			     struct vb2_queue *dst_vq)
 {
+	struct sh_veu_dev *veu = priv;
 	int ret;
 
 	memset(src_vq, 0, sizeof(*src_vq));
 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
-	src_vq->drv_priv = priv;
+	src_vq->drv_priv = veu;
 	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	src_vq->ops = &sh_veu_qops;
 	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->lock = &veu->fop_lock;
 
 	ret = vb2_queue_init(src_vq);
 	if (ret < 0)
@@ -988,10 +966,11 @@ static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
 	memset(dst_vq, 0, sizeof(*dst_vq));
 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
-	dst_vq->drv_priv = priv;
+	dst_vq->drv_priv = veu;
 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	dst_vq->ops = &sh_veu_qops;
 	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->lock = &veu->fop_lock;
 
 	return vb2_queue_init(dst_vq);
 }
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 6d885239b16a..8526bf5c8429 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -455,8 +455,8 @@ static struct vb2_ops isi_video_qops = {
 	.buf_queue		= buffer_queue,
 	.start_streaming	= start_streaming,
 	.stop_streaming		= stop_streaming,
-	.wait_prepare		= soc_camera_unlock,
-	.wait_finish		= soc_camera_lock,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
 };
 
 /* ------------------------------------------------------------------
@@ -465,6 +465,8 @@ static struct vb2_ops isi_video_qops = {
 static int isi_camera_init_videobuf(struct vb2_queue *q,
 				     struct soc_camera_device *icd)
 {
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	q->io_modes = VB2_MMAP;
 	q->drv_priv = icd;
@@ -472,6 +474,7 @@ static int isi_camera_init_videobuf(struct vb2_queue *q,
 	q->ops = &isi_video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &ici->host_lock;
 
 	return vb2_queue_init(q);
 }
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 0b3299dee05d..3435fd2ca8ec 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -435,14 +435,16 @@ static struct vb2_ops mx3_videobuf_ops = {
 	.buf_queue	= mx3_videobuf_queue,
 	.buf_cleanup	= mx3_videobuf_release,
 	.buf_init	= mx3_videobuf_init,
-	.wait_prepare	= soc_camera_unlock,
-	.wait_finish	= soc_camera_lock,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
 	.stop_streaming	= mx3_stop_streaming,
 };
 
 static int mx3_camera_init_videobuf(struct vb2_queue *q,
 				     struct soc_camera_device *icd)
 {
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	q->io_modes = VB2_MMAP | VB2_USERPTR;
 	q->drv_priv = icd;
@@ -450,6 +452,7 @@ static int mx3_camera_init_videobuf(struct vb2_queue *q,
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct mx3_camera_buffer);
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &ici->host_lock;
 
 	return vb2_queue_init(q);
 }
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 9f1473c0a0cf..279ab9f6ae38 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -804,62 +804,26 @@ error:
 	vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
 
-static void rcar_vin_videobuf_release(struct vb2_buffer *vb)
+/*
+ * Wait for capture to stop and all in-flight buffers to be finished with by
+ * the video hardware. This must be called under &priv->lock
+ *
+ */
+static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
 {
-	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct rcar_vin_priv *priv = ici->priv;
-	unsigned int i;
-	int buf_in_use = 0;
-
-	spin_lock_irq(&priv->lock);
-
-	/* Is the buffer in use by the VIN hardware? */
-	for (i = 0; i < MAX_BUFFER_NUM; i++) {
-		if (priv->queue_buf[i] == vb) {
-			buf_in_use = 1;
-			break;
-		}
-	}
-
-	if (buf_in_use) {
-		while (priv->state != STOPPED) {
-
-			/* issue stop if running */
-			if (priv->state == RUNNING)
-				rcar_vin_request_capture_stop(priv);
+	while (priv->state != STOPPED) {
+		/* issue stop if running */
+		if (priv->state == RUNNING)
+			rcar_vin_request_capture_stop(priv);
 
-			/* wait until capturing has been stopped */
-			if (priv->state == STOPPING) {
-				priv->request_to_stop = true;
-				spin_unlock_irq(&priv->lock);
-				wait_for_completion(&priv->capture_stop);
-				spin_lock_irq(&priv->lock);
-			}
-		}
-		/*
-		 * Capturing has now stopped. The buffer we have been asked
-		 * to release could be any of the current buffers in use, so
-		 * release all buffers that are in use by HW
-		 */
-		for (i = 0; i < MAX_BUFFER_NUM; i++) {
-			if (priv->queue_buf[i]) {
-				vb2_buffer_done(priv->queue_buf[i],
-					VB2_BUF_STATE_ERROR);
-				priv->queue_buf[i] = NULL;
-			}
+		/* wait until capturing has been stopped */
+		if (priv->state == STOPPING) {
+			priv->request_to_stop = true;
+			spin_unlock_irq(&priv->lock);
+			wait_for_completion(&priv->capture_stop);
+			spin_lock_irq(&priv->lock);
 		}
-	} else {
-		list_del_init(to_buf_list(vb));
 	}
-
-	spin_unlock_irq(&priv->lock);
-}
-
-static int rcar_vin_videobuf_init(struct vb2_buffer *vb)
-{
-	INIT_LIST_HEAD(to_buf_list(vb));
-	return 0;
 }
 
 static void rcar_vin_stop_streaming(struct vb2_queue *vq)
@@ -868,21 +832,34 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq)
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct rcar_vin_priv *priv = ici->priv;
 	struct list_head *buf_head, *tmp;
+	int i;
 
 	spin_lock_irq(&priv->lock);
-	list_for_each_safe(buf_head, tmp, &priv->capture)
+	rcar_vin_wait_stop_streaming(priv);
+
+	for (i = 0; i < MAX_BUFFER_NUM; i++) {
+		if (priv->queue_buf[i]) {
+			vb2_buffer_done(priv->queue_buf[i],
+					VB2_BUF_STATE_ERROR);
+			priv->queue_buf[i] = NULL;
+		}
+	}
+
+	list_for_each_safe(buf_head, tmp, &priv->capture) {
+		vb2_buffer_done(&list_entry(buf_head,
+					struct rcar_vin_buffer, list)->vb,
+				VB2_BUF_STATE_ERROR);
 		list_del_init(buf_head);
+	}
 	spin_unlock_irq(&priv->lock);
 }
 
 static struct vb2_ops rcar_vin_vb2_ops = {
 	.queue_setup	= rcar_vin_videobuf_setup,
-	.buf_init	= rcar_vin_videobuf_init,
-	.buf_cleanup	= rcar_vin_videobuf_release,
 	.buf_queue	= rcar_vin_videobuf_queue,
 	.stop_streaming	= rcar_vin_stop_streaming,
-	.wait_prepare	= soc_camera_unlock,
-	.wait_finish	= soc_camera_lock,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
 };
 
 static irqreturn_t rcar_vin_irq(int irq, void *data)
@@ -1808,6 +1785,8 @@ static int rcar_vin_querycap(struct soc_camera_host *ici,
 static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
 				   struct soc_camera_device *icd)
 {
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
 	vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	vq->io_modes = VB2_MMAP | VB2_USERPTR;
 	vq->drv_priv = icd;
@@ -1815,6 +1794,7 @@ static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
 	vq->mem_ops = &vb2_dma_contig_memops;
 	vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
 	vq->timestamp_flags  = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	vq->lock = &ici->host_lock;
 
 	return vb2_queue_init(vq);
 }
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 71787702d4a2..9ce202f53934 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -496,8 +496,8 @@ static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
 	.buf_queue	= sh_mobile_ceu_videobuf_queue,
 	.buf_cleanup	= sh_mobile_ceu_videobuf_release,
 	.buf_init	= sh_mobile_ceu_videobuf_init,
-	.wait_prepare	= soc_camera_unlock,
-	.wait_finish	= soc_camera_lock,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
 	.stop_streaming	= sh_mobile_ceu_stop_streaming,
 };
 
@@ -1661,6 +1661,8 @@ static int sh_mobile_ceu_querycap(struct soc_camera_host *ici,
 static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q,
 				       struct soc_camera_device *icd)
 {
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	q->io_modes = VB2_MMAP | VB2_USERPTR;
 	q->drv_priv = icd;
@@ -1668,6 +1670,7 @@ static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q,
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct sh_mobile_ceu_buffer);
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &ici->host_lock;
 
 	return vb2_queue_init(q);
 }
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index b3db51c82bde..cee7b56f8404 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -843,22 +843,6 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
 	return res;
 }
 
-void soc_camera_lock(struct vb2_queue *vq)
-{
-	struct soc_camera_device *icd = vb2_get_drv_priv(vq);
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	mutex_lock(&ici->host_lock);
-}
-EXPORT_SYMBOL(soc_camera_lock);
-
-void soc_camera_unlock(struct vb2_queue *vq)
-{
-	struct soc_camera_device *icd = vb2_get_drv_priv(vq);
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	mutex_unlock(&ici->host_lock);
-}
-EXPORT_SYMBOL(soc_camera_unlock);
-
 static struct v4l2_file_operations soc_camera_fops = {
 	.owner		= THIS_MODULE,
 	.open		= soc_camera_open,
@@ -1813,8 +1797,6 @@ eadddev:
 		mutex_unlock(&ici->clk_lock);
 	}
 eadd:
-	video_device_release(icd->vdev);
-	icd->vdev = NULL;
 	if (icd->vdev) {
 		video_device_release(icd->vdev);
 		icd->vdev = NULL;
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index d628d1a7cf9e..c44760b705da 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/ioctl.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/sched.h>
@@ -74,7 +75,7 @@
 #define VPE_DEF_BUFS_PER_JOB	1	/* default one buffer per batch job */
 
 /*
- * each VPE context can need up to 3 config desciptors, 7 input descriptors,
+ * each VPE context can need up to 3 config descriptors, 7 input descriptors,
  * 3 output descriptors, and 10 control descriptors
  */
 #define VPE_DESC_LIST_SIZE	(10 * VPDMA_DTD_DESC_SIZE +	\
@@ -373,7 +374,6 @@ struct vpe_dev {
 struct vpe_ctx {
 	struct v4l2_fh		fh;
 	struct vpe_dev		*dev;
-	struct v4l2_m2m_ctx	*m2m_ctx;
 	struct v4l2_ctrl_handler hdl;
 
 	unsigned int		field;			/* current field */
@@ -887,10 +887,10 @@ static int job_ready(void *priv)
 	if (ctx->deinterlacing && ctx->src_vbs[2] == NULL)
 		needed += 2;	/* need additional two most recent fields */
 
-	if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < needed)
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < needed)
 		return 0;
 
-	if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < needed)
+	if (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < needed)
 		return 0;
 
 	return 1;
@@ -1100,15 +1100,15 @@ static void device_run(void *priv)
 	struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST];
 
 	if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) {
-		ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 		WARN_ON(ctx->src_vbs[2] == NULL);
-		ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 		WARN_ON(ctx->src_vbs[1] == NULL);
 	}
 
-	ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 	WARN_ON(ctx->src_vbs[0] == NULL);
-	ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 	WARN_ON(ctx->dst_vb == NULL);
 
 	/* config descriptors */
@@ -1334,7 +1334,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
 finished:
 	vpe_dbg(ctx->dev, "finishing transaction\n");
 	ctx->bufs_completed = 0;
-	v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx);
+	v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx);
 handled:
 	return IRQ_HANDLED;
 }
@@ -1395,7 +1395,7 @@ static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 	struct vpe_q_data *q_data;
 	int i;
 
-	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 	if (!vq)
 		return -EINVAL;
 
@@ -1527,7 +1527,7 @@ static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f)
 	struct vb2_queue *vq;
 	int i;
 
-	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 	if (!vq)
 		return -EINVAL;
 
@@ -1739,52 +1739,6 @@ static int vpe_s_selection(struct file *file, void *fh,
 	return set_srcdst_params(ctx);
 }
 
-static int vpe_reqbufs(struct file *file, void *priv,
-		       struct v4l2_requestbuffers *reqbufs)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-
-	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int vpe_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-
-	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vpe_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-
-	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vpe_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-
-	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vpe_streamon(struct file *file, void *priv, enum v4l2_buf_type type)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-
-	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
-
-static int vpe_streamoff(struct file *file, void *priv, enum v4l2_buf_type type)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-
-	vpe_dump_regs(ctx->dev);
-	vpdma_dump_regs(ctx->dev->vpdma);
-
-	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
 /*
  * defines number of buffers/frames a context can process with VPE before
  * switching to a different context. default value is 1 buffer per context
@@ -1814,14 +1768,14 @@ static const struct v4l2_ctrl_ops vpe_ctrl_ops = {
 };
 
 static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
-	.vidioc_querycap	= vpe_querycap,
+	.vidioc_querycap		= vpe_querycap,
 
-	.vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt,
+	.vidioc_enum_fmt_vid_cap_mplane	= vpe_enum_fmt,
 	.vidioc_g_fmt_vid_cap_mplane	= vpe_g_fmt,
 	.vidioc_try_fmt_vid_cap_mplane	= vpe_try_fmt,
 	.vidioc_s_fmt_vid_cap_mplane	= vpe_s_fmt,
 
-	.vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt,
+	.vidioc_enum_fmt_vid_out_mplane	= vpe_enum_fmt,
 	.vidioc_g_fmt_vid_out_mplane	= vpe_g_fmt,
 	.vidioc_try_fmt_vid_out_mplane	= vpe_try_fmt,
 	.vidioc_s_fmt_vid_out_mplane	= vpe_s_fmt,
@@ -1829,16 +1783,15 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
 	.vidioc_g_selection		= vpe_g_selection,
 	.vidioc_s_selection		= vpe_s_selection,
 
-	.vidioc_reqbufs		= vpe_reqbufs,
-	.vidioc_querybuf	= vpe_querybuf,
+	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
 
-	.vidioc_qbuf		= vpe_qbuf,
-	.vidioc_dqbuf		= vpe_dqbuf,
-
-	.vidioc_streamon	= vpe_streamon,
-	.vidioc_streamoff	= vpe_streamoff,
-	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 };
 
 /*
@@ -1910,33 +1863,40 @@ static int vpe_buf_prepare(struct vb2_buffer *vb)
 static void vpe_buf_queue(struct vb2_buffer *vb)
 {
 	struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 }
 
-static void vpe_wait_prepare(struct vb2_queue *q)
+static int vpe_start_streaming(struct vb2_queue *q, unsigned int count)
 {
-	struct vpe_ctx *ctx = vb2_get_drv_priv(q);
-	vpe_unlock(ctx);
+	/* currently we do nothing here */
+
+	return 0;
 }
 
-static void vpe_wait_finish(struct vb2_queue *q)
+static void vpe_stop_streaming(struct vb2_queue *q)
 {
 	struct vpe_ctx *ctx = vb2_get_drv_priv(q);
-	vpe_lock(ctx);
+
+	vpe_dump_regs(ctx->dev);
+	vpdma_dump_regs(ctx->dev->vpdma);
 }
 
 static struct vb2_ops vpe_qops = {
 	.queue_setup	 = vpe_queue_setup,
 	.buf_prepare	 = vpe_buf_prepare,
 	.buf_queue	 = vpe_buf_queue,
-	.wait_prepare	 = vpe_wait_prepare,
-	.wait_finish	 = vpe_wait_finish,
+	.wait_prepare	 = vb2_ops_wait_prepare,
+	.wait_finish	 = vb2_ops_wait_finish,
+	.start_streaming = vpe_start_streaming,
+	.stop_streaming  = vpe_stop_streaming,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq,
 		      struct vb2_queue *dst_vq)
 {
 	struct vpe_ctx *ctx = priv;
+	struct vpe_dev *dev = ctx->dev;
 	int ret;
 
 	memset(src_vq, 0, sizeof(*src_vq));
@@ -1947,6 +1907,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
 	src_vq->ops = &vpe_qops;
 	src_vq->mem_ops = &vb2_dma_contig_memops;
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &dev->dev_mutex;
 
 	ret = vb2_queue_init(src_vq);
 	if (ret)
@@ -1960,6 +1921,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
 	dst_vq->ops = &vpe_qops;
 	dst_vq->mem_ops = &vb2_dma_contig_memops;
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &dev->dev_mutex;
 
 	return vb2_queue_init(dst_vq);
 }
@@ -1981,9 +1943,9 @@ static const struct v4l2_ctrl_config vpe_bufs_per_job = {
 static int vpe_open(struct file *file)
 {
 	struct vpe_dev *dev = video_drvdata(file);
-	struct vpe_ctx *ctx = NULL;
 	struct vpe_q_data *s_q_data;
 	struct v4l2_ctrl_handler *hdl;
+	struct vpe_ctx *ctx;
 	int ret;
 
 	vpe_dbg(dev, "vpe_open\n");
@@ -2056,10 +2018,10 @@ static int vpe_open(struct file *file)
 	if (ret)
 		goto exit_fh;
 
-	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
 
-	if (IS_ERR(ctx->m2m_ctx)) {
-		ret = PTR_ERR(ctx->m2m_ctx);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
 		goto exit_fh;
 	}
 
@@ -2078,7 +2040,7 @@ static int vpe_open(struct file *file)
 	ctx->load_mmrs = true;
 
 	vpe_dbg(dev, "created instance %p, m2m_ctx: %p\n",
-		ctx, ctx->m2m_ctx);
+		ctx, ctx->fh.m2m_ctx);
 
 	mutex_unlock(&dev->dev_mutex);
 
@@ -2116,7 +2078,7 @@ static int vpe_release(struct file *file)
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	v4l2_ctrl_handler_free(&ctx->hdl);
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 
 	kfree(ctx);
 
@@ -2133,39 +2095,13 @@ static int vpe_release(struct file *file)
 	return 0;
 }
 
-static unsigned int vpe_poll(struct file *file,
-			     struct poll_table_struct *wait)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-	struct vpe_dev *dev = ctx->dev;
-	int ret;
-
-	mutex_lock(&dev->dev_mutex);
-	ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
-	mutex_unlock(&dev->dev_mutex);
-	return ret;
-}
-
-static int vpe_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct vpe_ctx *ctx = file2ctx(file);
-	struct vpe_dev *dev = ctx->dev;
-	int ret;
-
-	if (mutex_lock_interruptible(&dev->dev_mutex))
-		return -ERESTARTSYS;
-	ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-	mutex_unlock(&dev->dev_mutex);
-	return ret;
-}
-
 static const struct v4l2_file_operations vpe_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vpe_open,
 	.release	= vpe_release,
-	.poll		= vpe_poll,
+	.poll		= v4l2_m2m_fop_poll,
 	.unlocked_ioctl	= video_ioctl2,
-	.mmap		= vpe_mmap,
+	.mmap		= v4l2_m2m_fop_mmap,
 };
 
 static struct video_device vpe_videodev = {
@@ -2367,8 +2303,6 @@ static const struct of_device_id vpe_of_match[] = {
 	},
 	{},
 };
-#else
-#define vpe_of_match NULL
 #endif
 
 static struct platform_driver vpe_pdrv = {
@@ -2376,7 +2310,7 @@ static struct platform_driver vpe_pdrv = {
 	.remove		= vpe_remove,
 	.driver		= {
 		.name	= VPE_MODULE_NAME,
-		.of_match_table = vpe_of_match,
+		.of_match_table = of_match_ptr(vpe_of_match),
 	},
 };
 
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 857e7866e8bc..32a798f2d953 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -689,7 +689,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = {
 
 static const char * const vivid_ctrl_colorspace_strings[] = {
 	"SMPTE 170M",
-	"REC 709",
+	"Rec. 709",
 	"sRGB",
 	"AdobeRGB",
 	"BT.2020",
@@ -716,7 +716,7 @@ static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
 	"xvYCC 601",
 	"xvYCC 709",
 	"sYCC",
-	"BT.2020 Non-Constant Luminance",
+	"BT.2020",
 	"BT.2020 Constant Luminance",
 	"SMPTE 240M",
 	NULL,
diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index fc9c6536ba02..34493f435d5a 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -352,13 +352,14 @@ static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b,
 		{ COEFF(0.5, 224),     COEFF(-0.4629, 224), COEFF(-0.0405, 224) },
 	};
 	bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
+	unsigned y_offset = full ? 0 : 16;
 	int lin_y, yc;
 
 	switch (tpg->real_ycbcr_enc) {
 	case V4L2_YCBCR_ENC_601:
 	case V4L2_YCBCR_ENC_XV601:
 	case V4L2_YCBCR_ENC_SYCC:
-		rgb2ycbcr(full ? bt601_full : bt601, r, g, b, 16, y, cb, cr);
+		rgb2ycbcr(full ? bt601_full : bt601, r, g, b, y_offset, y, cb, cr);
 		break;
 	case V4L2_YCBCR_ENC_BT2020:
 		rgb2ycbcr(bt2020, r, g, b, 16, y, cb, cr);
@@ -384,7 +385,7 @@ static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b,
 	case V4L2_YCBCR_ENC_709:
 	case V4L2_YCBCR_ENC_XV709:
 	default:
-		rgb2ycbcr(full ? rec709_full : rec709, r, g, b, 0, y, cb, cr);
+		rgb2ycbcr(full ? rec709_full : rec709, r, g, b, y_offset, y, cb, cr);
 		break;
 	}
 }
@@ -439,13 +440,14 @@ static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr,
 		{ COEFF(1, 219), COEFF(1.8814, 224),  COEFF(0, 224)       },
 	};
 	bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
+	unsigned y_offset = full ? 0 : 16;
 	int lin_r, lin_g, lin_b, lin_y;
 
 	switch (tpg->real_ycbcr_enc) {
 	case V4L2_YCBCR_ENC_601:
 	case V4L2_YCBCR_ENC_XV601:
 	case V4L2_YCBCR_ENC_SYCC:
-		ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, 16, r, g, b);
+		ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, y_offset, r, g, b);
 		break;
 	case V4L2_YCBCR_ENC_BT2020:
 		ycbcr2rgb(bt2020, y, cb, cr, 16, r, g, b);
@@ -480,7 +482,7 @@ static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr,
 	case V4L2_YCBCR_ENC_709:
 	case V4L2_YCBCR_ENC_XV709:
 	default:
-		ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, 16, r, g, b);
+		ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, y_offset, r, g, b);
 		break;
 	}
 }
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index 9dc463a40ed3..bd8b1c760b3f 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -20,7 +20,6 @@
 #ifndef _VIVID_TPG_H_
 #define _VIVID_TPG_H_
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/random.h>
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 12467191dff4..989e96f7e360 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -16,7 +16,6 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
-#include <linux/platform_data/vsp1.h>
 
 #include <media/media-device.h>
 #include <media/v4l2-device.h>
@@ -40,9 +39,20 @@ struct vsp1_uds;
 #define VSP1_MAX_UDS		3
 #define VSP1_MAX_WPF		4
 
+#define VSP1_HAS_LIF		(1 << 0)
+#define VSP1_HAS_LUT		(1 << 1)
+#define VSP1_HAS_SRU		(1 << 2)
+
+struct vsp1_platform_data {
+	unsigned int features;
+	unsigned int rpf_count;
+	unsigned int uds_count;
+	unsigned int wpf_count;
+};
+
 struct vsp1_device {
 	struct device *dev;
-	struct vsp1_platform_data *pdata;
+	struct vsp1_platform_data pdata;
 
 	void __iomem *mmio;
 	struct clk *clock;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index b21f381a9862..401e2b77a0b6 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -20,7 +20,7 @@
 #include "vsp1_bru.h"
 #include "vsp1_rwpf.h"
 
-#define BRU_MIN_SIZE				4U
+#define BRU_MIN_SIZE				1U
 #define BRU_MAX_SIZE				8190U
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 5eb16e87d53f..913485a90e97 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -40,7 +40,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
 	irqreturn_t ret = IRQ_NONE;
 	unsigned int i;
 
-	for (i = 0; i < vsp1->pdata->wpf_count; ++i) {
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
 		struct vsp1_rwpf *wpf = vsp1->wpf[i];
 		struct vsp1_pipeline *pipe;
 		u32 status;
@@ -181,7 +181,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 	list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities);
 
-	if (vsp1->pdata->features & VSP1_HAS_LIF) {
+	if (vsp1->pdata.features & VSP1_HAS_LIF) {
 		vsp1->lif = vsp1_lif_create(vsp1);
 		if (IS_ERR(vsp1->lif)) {
 			ret = PTR_ERR(vsp1->lif);
@@ -191,7 +191,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities);
 	}
 
-	if (vsp1->pdata->features & VSP1_HAS_LUT) {
+	if (vsp1->pdata.features & VSP1_HAS_LUT) {
 		vsp1->lut = vsp1_lut_create(vsp1);
 		if (IS_ERR(vsp1->lut)) {
 			ret = PTR_ERR(vsp1->lut);
@@ -201,7 +201,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities);
 	}
 
-	for (i = 0; i < vsp1->pdata->rpf_count; ++i) {
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
 		struct vsp1_rwpf *rpf;
 
 		rpf = vsp1_rpf_create(vsp1, i);
@@ -214,7 +214,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		list_add_tail(&rpf->entity.list_dev, &vsp1->entities);
 	}
 
-	if (vsp1->pdata->features & VSP1_HAS_SRU) {
+	if (vsp1->pdata.features & VSP1_HAS_SRU) {
 		vsp1->sru = vsp1_sru_create(vsp1);
 		if (IS_ERR(vsp1->sru)) {
 			ret = PTR_ERR(vsp1->sru);
@@ -224,7 +224,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities);
 	}
 
-	for (i = 0; i < vsp1->pdata->uds_count; ++i) {
+	for (i = 0; i < vsp1->pdata.uds_count; ++i) {
 		struct vsp1_uds *uds;
 
 		uds = vsp1_uds_create(vsp1, i);
@@ -237,7 +237,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		list_add_tail(&uds->entity.list_dev, &vsp1->entities);
 	}
 
-	for (i = 0; i < vsp1->pdata->wpf_count; ++i) {
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
 		struct vsp1_rwpf *wpf;
 
 		wpf = vsp1_wpf_create(vsp1, i);
@@ -261,7 +261,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 			goto done;
 	}
 
-	if (vsp1->pdata->features & VSP1_HAS_LIF) {
+	if (vsp1->pdata.features & VSP1_HAS_LIF) {
 		ret = media_entity_create_link(
 			&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE,
 			&vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0);
@@ -294,7 +294,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
 	/* Reset any channel that might be running. */
 	status = vsp1_read(vsp1, VI6_STATUS);
 
-	for (i = 0; i < vsp1->pdata->wpf_count; ++i) {
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
 		unsigned int timeout;
 
 		if (!(status & VI6_STATUS_SYS_ACT(i)))
@@ -318,10 +318,10 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
 	vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) |
 		   (8 << VI6_CLK_DCSWT_CSTRW_SHIFT));
 
-	for (i = 0; i < vsp1->pdata->rpf_count; ++i)
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i)
 		vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED);
 
-	for (i = 0; i < vsp1->pdata->uds_count; ++i)
+	for (i = 0; i < vsp1->pdata.uds_count; ++i)
 		vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
 
 	vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED);
@@ -428,28 +428,36 @@ static const struct dev_pm_ops vsp1_pm_ops = {
  * Platform Driver
  */
 
-static int vsp1_validate_platform_data(struct platform_device *pdev,
-				       struct vsp1_platform_data *pdata)
+static int vsp1_parse_dt(struct vsp1_device *vsp1)
 {
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "missing platform data\n");
-		return -EINVAL;
-	}
+	struct device_node *np = vsp1->dev->of_node;
+	struct vsp1_platform_data *pdata = &vsp1->pdata;
+
+	if (of_property_read_bool(np, "renesas,has-lif"))
+		pdata->features |= VSP1_HAS_LIF;
+	if (of_property_read_bool(np, "renesas,has-lut"))
+		pdata->features |= VSP1_HAS_LUT;
+	if (of_property_read_bool(np, "renesas,has-sru"))
+		pdata->features |= VSP1_HAS_SRU;
+
+	of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count);
+	of_property_read_u32(np, "renesas,#uds", &pdata->uds_count);
+	of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count);
 
 	if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) {
-		dev_err(&pdev->dev, "invalid number of RPF (%u)\n",
+		dev_err(vsp1->dev, "invalid number of RPF (%u)\n",
 			pdata->rpf_count);
 		return -EINVAL;
 	}
 
 	if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) {
-		dev_err(&pdev->dev, "invalid number of UDS (%u)\n",
+		dev_err(vsp1->dev, "invalid number of UDS (%u)\n",
 			pdata->uds_count);
 		return -EINVAL;
 	}
 
 	if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) {
-		dev_err(&pdev->dev, "invalid number of WPF (%u)\n",
+		dev_err(vsp1->dev, "invalid number of WPF (%u)\n",
 			pdata->wpf_count);
 		return -EINVAL;
 	}
@@ -457,33 +465,6 @@ static int vsp1_validate_platform_data(struct platform_device *pdev,
 	return 0;
 }
 
-static struct vsp1_platform_data *
-vsp1_get_platform_data(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	struct vsp1_platform_data *pdata;
-
-	if (!IS_ENABLED(CONFIG_OF) || np == NULL)
-		return pdev->dev.platform_data;
-
-	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-	if (pdata == NULL)
-		return NULL;
-
-	if (of_property_read_bool(np, "renesas,has-lif"))
-		pdata->features |= VSP1_HAS_LIF;
-	if (of_property_read_bool(np, "renesas,has-lut"))
-		pdata->features |= VSP1_HAS_LUT;
-	if (of_property_read_bool(np, "renesas,has-sru"))
-		pdata->features |= VSP1_HAS_SRU;
-
-	of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count);
-	of_property_read_u32(np, "renesas,#uds", &pdata->uds_count);
-	of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count);
-
-	return pdata;
-}
-
 static int vsp1_probe(struct platform_device *pdev)
 {
 	struct vsp1_device *vsp1;
@@ -499,11 +480,7 @@ static int vsp1_probe(struct platform_device *pdev)
 	mutex_init(&vsp1->lock);
 	INIT_LIST_HEAD(&vsp1->entities);
 
-	vsp1->pdata = vsp1_get_platform_data(pdev);
-	if (vsp1->pdata == NULL)
-		return -ENODEV;
-
-	ret = vsp1_validate_platform_data(pdev, vsp1->pdata);
+	ret = vsp1_parse_dt(vsp1);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 80bedc554ee3..0bc0471746c9 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -26,11 +26,6 @@
  * Device Access
  */
 
-static inline u32 vsp1_hsit_read(struct vsp1_hsit *hsit, u32 reg)
-{
-	return vsp1_read(hsit->entity.vsp1, reg);
-}
-
 static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data)
 {
 	vsp1_write(hsit->entity.vsp1, reg, data);
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 55f163d32d15..da3c573e1efc 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -43,12 +43,12 @@
 #define VI6_DISP_IRQ_ENB		0x0078
 #define VI6_DISP_IRQ_ENB_DSTE		(1 << 8)
 #define VI6_DISP_IRQ_ENB_MAEE		(1 << 5)
-#define VI6_DISP_IRQ_ENB_LNEE(n)	(1 << ((n) + 4))
+#define VI6_DISP_IRQ_ENB_LNEE(n)	(1 << (n))
 
 #define VI6_DISP_IRQ_STA		0x007c
 #define VI6_DISP_IRQ_STA_DSE		(1 << 8)
 #define VI6_DISP_IRQ_STA_MAE		(1 << 5)
-#define VI6_DISP_IRQ_STA_LNE(n)		(1 << ((n) + 4))
+#define VI6_DISP_IRQ_STA_LNE(n)		(1 << (n))
 
 #define VI6_WPF_LINE_COUNT(n)		(0x0084 + (n) * 4)
 #define VI6_WPF_LINE_COUNT_MASK		(0x1fffff << 0)
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index d14d26b718ef..3294529a3108 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -106,11 +106,22 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
 			+ crop->left * fmtinfo->bpp[0] / 8;
 	pstride = format->plane_fmt[0].bytesperline
 		<< VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
+
+	vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
+		       rpf->buf_addr[0] + rpf->offsets[0]);
+
 	if (format->num_planes > 1) {
 		rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline
 				+ crop->left * fmtinfo->bpp[1] / 8;
 		pstride |= format->plane_fmt[1].bytesperline
 			<< VI6_RPF_SRCM_PSTRIDE_C_SHIFT;
+
+		vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0,
+			       rpf->buf_addr[1] + rpf->offsets[1]);
+
+		if (format->num_planes > 2)
+			vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
+				       rpf->buf_addr[2] + rpf->offsets[1]);
 	}
 
 	vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride);
@@ -179,6 +190,13 @@ static void rpf_vdev_queue(struct vsp1_video *video,
 			   struct vsp1_video_buffer *buf)
 {
 	struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video);
+	unsigned int i;
+
+	for (i = 0; i < 3; ++i)
+		rpf->buf_addr[i] = buf->addr[i];
+
+	if (!vsp1_entity_is_streaming(&rpf->entity))
+		return;
 
 	vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
 		       buf->addr[0] + rpf->offsets[0]);
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 28dd9e7b3838..2cf1f13d3bf9 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -39,6 +39,7 @@ struct vsp1_rwpf {
 	struct v4l2_rect crop;
 
 	unsigned int offsets[2];
+	dma_addr_t buf_addr[3];
 };
 
 static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 6e057762c933..1d2b3a2f1573 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -92,19 +92,20 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 		return 0;
 	}
 
-	/* Sources. If the pipeline has a single input configure it as the
-	 * master layer. Otherwise configure all inputs as sub-layers and
-	 * select the virtual RPF as the master layer.
+	/* Sources. If the pipeline has a single input and BRU is not used,
+	 * configure it as the master layer. Otherwise configure all
+	 * inputs as sub-layers and select the virtual RPF as the master
+	 * layer.
 	 */
 	for (i = 0; i < pipe->num_inputs; ++i) {
 		struct vsp1_rwpf *input = pipe->inputs[i];
 
-		srcrpf |= pipe->num_inputs == 1
+		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
 			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
 			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
 	}
 
-	if (pipe->num_inputs > 1)
+	if (pipe->bru || pipe->num_inputs > 1)
 		srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST;
 
 	vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf);
@@ -280,7 +281,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 	 * except for the WPF0 source link if a LIF is present.
 	 */
 	flags = MEDIA_LNK_FL_ENABLED;
-	if (!(vsp1->pdata->features & VSP1_HAS_LIF) || index != 0)
+	if (!(vsp1->pdata.features & VSP1_HAS_LIF) || index != 0)
 		flags |= MEDIA_LNK_FL_IMMUTABLE;
 
 	ret = media_entity_create_link(&wpf->entity.subdev.entity,
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index a739ad492e7b..ea9308796741 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -129,11 +129,11 @@ static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
 	} else if (curvol < vol) {
 		outb(0x98, isa->io);	/* volume up + sigstr + on	*/
 		for (; curvol < vol; curvol++)
-			udelay(3000);
+			mdelay(3);
 	} else if (curvol > vol) {
 		outb(0x58, isa->io);	/* volume down + sigstr + on	*/
 		for (; curvol > vol; curvol--)
-			udelay(3000);
+			mdelay(3);
 	}
 	outb(0xd8, isa->io);		/* volume steady + sigstr + on	*/
 	rt->curvol = vol;
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c
index f1a0867789fe..43d1ea53cb66 100644
--- a/drivers/media/radio/tea575x.c
+++ b/drivers/media/radio/tea575x.c
@@ -247,10 +247,9 @@ static int vidioc_querycap(struct file *file, void  *priv,
 	return 0;
 }
 
-static int vidioc_enum_freq_bands(struct file *file, void *priv,
-					 struct v4l2_frequency_band *band)
+int snd_tea575x_enum_freq_bands(struct snd_tea575x *tea,
+					struct v4l2_frequency_band *band)
 {
-	struct snd_tea575x *tea = video_drvdata(file);
 	int index;
 
 	if (band->tuner != 0)
@@ -279,18 +278,25 @@ static int vidioc_enum_freq_bands(struct file *file, void *priv,
 
 	return 0;
 }
+EXPORT_SYMBOL(snd_tea575x_enum_freq_bands);
 
-static int vidioc_g_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *v)
+static int vidioc_enum_freq_bands(struct file *file, void *priv,
+					 struct v4l2_frequency_band *band)
 {
 	struct snd_tea575x *tea = video_drvdata(file);
+
+	return snd_tea575x_enum_freq_bands(tea, band);
+}
+
+int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v)
+{
 	struct v4l2_frequency_band band_fm = { 0, };
 
 	if (v->index > 0)
 		return -EINVAL;
 
 	snd_tea575x_read(tea);
-	vidioc_enum_freq_bands(file, priv, &band_fm);
+	snd_tea575x_enum_freq_bands(tea, &band_fm);
 
 	memset(v, 0, sizeof(*v));
 	strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
@@ -304,6 +310,15 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 	v->signal = tea->tuned ? 0xffff : 0;
 	return 0;
 }
+EXPORT_SYMBOL(snd_tea575x_g_tuner);
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *v)
+{
+	struct snd_tea575x *tea = video_drvdata(file);
+
+	return snd_tea575x_g_tuner(tea, v);
+}
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 					const struct v4l2_tuner *v)
@@ -356,10 +371,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
-					const struct v4l2_hw_freq_seek *a)
+int snd_tea575x_s_hw_freq_seek(struct file *file, struct snd_tea575x *tea,
+				const struct v4l2_hw_freq_seek *a)
 {
-	struct snd_tea575x *tea = video_drvdata(file);
 	unsigned long timeout;
 	int i, spacing;
 
@@ -442,6 +456,15 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
 	snd_tea575x_set_freq(tea);
 	return -ENODATA;
 }
+EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek);
+
+static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
+					const struct v4l2_hw_freq_seek *a)
+{
+	struct snd_tea575x *tea = video_drvdata(file);
+
+	return snd_tea575x_s_hw_freq_seek(file, tea, a);
+}
 
 static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
 {
diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c
index 09632cb26cb6..cfaeb2417fbb 100644
--- a/drivers/media/radio/wl128x/fmdrv_rx.c
+++ b/drivers/media/radio/wl128x/fmdrv_rx.c
@@ -785,22 +785,6 @@ int fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
 	return 0;
 }
 
-/* Returns current RDS operation mode */
-int fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
-{
-	if (fmdev->curr_fmmode != FM_MODE_RX)
-		return -EPERM;
-
-	if (rds_mode == NULL) {
-		fmerr("Invalid memory\n");
-		return -ENOMEM;
-	}
-
-	*rds_mode = fmdev->rx.rds_mode;
-
-	return 0;
-}
-
 /* Configures Alternate Frequency switch mode */
 int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
 {
diff --git a/drivers/media/radio/wl128x/fmdrv_rx.h b/drivers/media/radio/wl128x/fmdrv_rx.h
index 32add81f8d87..23922188882f 100644
--- a/drivers/media/radio/wl128x/fmdrv_rx.h
+++ b/drivers/media/radio/wl128x/fmdrv_rx.h
@@ -40,7 +40,6 @@ void fm_rx_reset_station_info(struct fmdev *);
 int fm_rx_seek(struct fmdev *, u32, u32, u32);
 
 int fm_rx_get_rds_mode(struct fmdev *, u8 *);
-int fm_rx_get_rds_system(struct fmdev *, u8 *);
 int fm_rx_get_mute_mode(struct fmdev *, u8 *);
 int fm_rx_get_volume(struct fmdev *, u16 *);
 int fm_rx_get_band_freq_range(struct fmdev *,
diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig
index 580715c7fc5e..a896d3c83a1c 100644
--- a/drivers/media/rc/img-ir/Kconfig
+++ b/drivers/media/rc/img-ir/Kconfig
@@ -60,3 +60,18 @@ config IR_IMG_SANYO
 	help
 	   Say Y here to enable support for the Sanyo protocol (used by Sanyo,
 	   Aiwa, Chinon remotes) in the ImgTec infrared decoder block.
+
+config IR_IMG_RC5
+	bool "Philips RC5 protocol support"
+	depends on IR_IMG_HW
+	help
+	   Say Y here to enable support for the RC5 protocol in the ImgTec
+	   infrared decoder block.
+
+config IR_IMG_RC6
+	bool "Philips RC6 protocol support"
+	depends on IR_IMG_HW
+	help
+	   Say Y here to enable support for the RC6 protocol in the ImgTec
+	   infrared decoder block.
+	   Note: This version only supports mode 0.
diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile
index 92a459d99509..8e6d458e66ad 100644
--- a/drivers/media/rc/img-ir/Makefile
+++ b/drivers/media/rc/img-ir/Makefile
@@ -6,6 +6,8 @@ img-ir-$(CONFIG_IR_IMG_JVC)	+= img-ir-jvc.o
 img-ir-$(CONFIG_IR_IMG_SONY)	+= img-ir-sony.o
 img-ir-$(CONFIG_IR_IMG_SHARP)	+= img-ir-sharp.o
 img-ir-$(CONFIG_IR_IMG_SANYO)	+= img-ir-sanyo.o
+img-ir-$(CONFIG_IR_IMG_RC5)	+= img-ir-rc5.o
+img-ir-$(CONFIG_IR_IMG_RC6)	+= img-ir-rc6.o
 img-ir-objs			:= $(img-ir-y)
 
 obj-$(CONFIG_IR_IMG)		+= img-ir.o
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 2fd47c9bf5d8..7bb71bc9f534 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -42,6 +42,12 @@ static struct img_ir_decoder *img_ir_decoders[] = {
 #ifdef CONFIG_IR_IMG_SANYO
 	&img_ir_sanyo,
 #endif
+#ifdef CONFIG_IR_IMG_RC5
+	&img_ir_rc5,
+#endif
+#ifdef CONFIG_IR_IMG_RC6
+	&img_ir_rc6,
+#endif
 	NULL
 };
 
@@ -52,6 +58,11 @@ static struct img_ir_decoder *img_ir_decoders[] = {
 
 #define IMG_IR_QUIRK_CODE_BROKEN	0x1	/* Decode is broken */
 #define IMG_IR_QUIRK_CODE_LEN_INCR	0x2	/* Bit length needs increment */
+/*
+ * The decoder generates rapid interrupts without actually having
+ * received any new data after an incomplete IR code is decoded.
+ */
+#define IMG_IR_QUIRK_CODE_IRQ		0x4
 
 /* functions for preprocessing timings, ensuring max is set */
 
@@ -542,6 +553,7 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
 	 */
 	spin_unlock_irq(&priv->lock);
 	del_timer_sync(&hw->end_timer);
+	del_timer_sync(&hw->suspend_timer);
 	spin_lock_irq(&priv->lock);
 
 	hw->stopping = false;
@@ -806,20 +818,24 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw)
 	struct img_ir_priv_hw *hw = &priv->hw;
 	const struct img_ir_decoder *dec = hw->decoder;
 	int ret = IMG_IR_SCANCODE;
-	u32 scancode;
-	enum rc_type protocol = RC_TYPE_UNKNOWN;
+	struct img_ir_scancode_req request;
+
+	request.protocol = RC_TYPE_UNKNOWN;
+	request.toggle   = 0;
 
 	if (dec->scancode)
-		ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols);
+		ret = dec->scancode(len, raw, hw->enabled_protocols, &request);
 	else if (len >= 32)
-		scancode = (u32)raw;
+		request.scancode = (u32)raw;
 	else if (len < 32)
-		scancode = (u32)raw & ((1 << len)-1);
+		request.scancode = (u32)raw & ((1 << len)-1);
 	dev_dbg(priv->dev, "data (%u bits) = %#llx\n",
 		len, (unsigned long long)raw);
 	if (ret == IMG_IR_SCANCODE) {
-		dev_dbg(priv->dev, "decoded scan code %#x\n", scancode);
-		rc_keydown(hw->rdev, protocol, scancode, 0);
+		dev_dbg(priv->dev, "decoded scan code %#x, toggle %u\n",
+			request.scancode, request.toggle);
+		rc_keydown(hw->rdev, request.protocol, request.scancode,
+			   request.toggle);
 		img_ir_end_repeat(priv);
 	} else if (ret == IMG_IR_REPEATCODE) {
 		if (hw->mode == IMG_IR_M_REPEATING) {
@@ -857,6 +873,29 @@ static void img_ir_end_timer(unsigned long arg)
 	spin_unlock_irq(&priv->lock);
 }
 
+/*
+ * Timer function to re-enable the current protocol after it had been
+ * cleared when invalid interrupts were generated due to a quirk in the
+ * img-ir decoder.
+ */
+static void img_ir_suspend_timer(unsigned long arg)
+{
+	struct img_ir_priv *priv = (struct img_ir_priv *)arg;
+
+	spin_lock_irq(&priv->lock);
+	/*
+	 * Don't overwrite enabled valid/match IRQs if they have already been
+	 * changed by e.g. a filter change.
+	 */
+	if ((priv->hw.quirk_suspend_irq & IMG_IR_IRQ_EDGE) ==
+				img_ir_read(priv, IMG_IR_IRQ_ENABLE))
+		img_ir_write(priv, IMG_IR_IRQ_ENABLE,
+					priv->hw.quirk_suspend_irq);
+	/* enable */
+	img_ir_write(priv, IMG_IR_CONTROL, priv->hw.reg_timings.ctrl);
+	spin_unlock_irq(&priv->lock);
+}
+
 #ifdef CONFIG_COMMON_CLK
 static void img_ir_change_frequency(struct img_ir_priv *priv,
 				    struct clk_notifier_data *change)
@@ -922,15 +961,38 @@ void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status)
 	if (!hw->decoder)
 		return;
 
+	ct = hw->decoder->control.code_type;
+
 	ir_status = img_ir_read(priv, IMG_IR_STATUS);
-	if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)))
+	if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) {
+		if (!(priv->hw.ct_quirks[ct] & IMG_IR_QUIRK_CODE_IRQ) ||
+				hw->stopping)
+			return;
+		/*
+		 * The below functionality is added as a work around to stop
+		 * multiple Interrupts generated when an incomplete IR code is
+		 * received by the decoder.
+		 * The decoder generates rapid interrupts without actually
+		 * having received any new data. After a single interrupt it's
+		 * expected to clear up, but instead multiple interrupts are
+		 * rapidly generated. only way to get out of this loop is to
+		 * reset the control register after a short delay.
+		 */
+		img_ir_write(priv, IMG_IR_CONTROL, 0);
+		hw->quirk_suspend_irq = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
+		img_ir_write(priv, IMG_IR_IRQ_ENABLE,
+			     hw->quirk_suspend_irq & IMG_IR_IRQ_EDGE);
+
+		/* Timer activated to re-enable the protocol. */
+		mod_timer(&hw->suspend_timer,
+			  jiffies + msecs_to_jiffies(5));
 		return;
+	}
 	ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2);
 	img_ir_write(priv, IMG_IR_STATUS, ir_status);
 
 	len = (ir_status & IMG_IR_RXDLEN) >> IMG_IR_RXDLEN_SHIFT;
 	/* some versions report wrong length for certain code types */
-	ct = hw->decoder->control.code_type;
 	if (hw->ct_quirks[ct] & IMG_IR_QUIRK_CODE_LEN_INCR)
 		++len;
 
@@ -972,7 +1034,7 @@ static void img_ir_probe_hw_caps(struct img_ir_priv *priv)
 	hw->ct_quirks[IMG_IR_CODETYPE_PULSELEN]
 		|= IMG_IR_QUIRK_CODE_LEN_INCR;
 	hw->ct_quirks[IMG_IR_CODETYPE_BIPHASE]
-		|= IMG_IR_QUIRK_CODE_BROKEN;
+		|= IMG_IR_QUIRK_CODE_IRQ;
 	hw->ct_quirks[IMG_IR_CODETYPE_2BITPULSEPOS]
 		|= IMG_IR_QUIRK_CODE_BROKEN;
 }
@@ -991,6 +1053,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
 
 	/* Set up the end timer */
 	setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv);
+	setup_timer(&hw->suspend_timer, img_ir_suspend_timer,
+				(unsigned long)priv);
 
 	/* Register a clock notifier */
 	if (!IS_ERR(priv->clk)) {
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index 5c2b216c5fe3..91a297731661 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -133,6 +133,20 @@ struct img_ir_timing_regvals {
 #define IMG_IR_REPEATCODE	1	/* repeat the previous code */
 
 /**
+ * struct img_ir_scancode_req - Scancode request data.
+ * @protocol:	Protocol code of received message (defaults to
+ *		RC_TYPE_UNKNOWN).
+ * @scancode:	Scan code of received message (must be written by
+ *		handler if IMG_IR_SCANCODE is returned).
+ * @toggle:	Toggle bit (defaults to 0).
+ */
+struct img_ir_scancode_req {
+	enum rc_type protocol;
+	u32 scancode;
+	u8 toggle;
+};
+
+/**
  * struct img_ir_decoder - Decoder settings for an IR protocol.
  * @type:	Protocol types bitmap.
  * @tolerance:	Timing tolerance as a percentage (default 10%).
@@ -162,8 +176,8 @@ struct img_ir_decoder {
 	struct img_ir_control		control;
 
 	/* scancode logic */
-	int (*scancode)(int len, u64 raw, enum rc_type *protocol,
-			u32 *scancode, u64 enabled_protocols);
+	int (*scancode)(int len, u64 raw, u64 enabled_protocols,
+			struct img_ir_scancode_req *request);
 	int (*filter)(const struct rc_scancode_filter *in,
 		      struct img_ir_filter *out, u64 protocols);
 };
@@ -173,6 +187,8 @@ extern struct img_ir_decoder img_ir_jvc;
 extern struct img_ir_decoder img_ir_sony;
 extern struct img_ir_decoder img_ir_sharp;
 extern struct img_ir_decoder img_ir_sanyo;
+extern struct img_ir_decoder img_ir_rc5;
+extern struct img_ir_decoder img_ir_rc6;
 
 /**
  * struct img_ir_reg_timings - Reg values for decoder timings at clock rate.
@@ -204,6 +220,7 @@ enum img_ir_mode {
  * @rdev:		Remote control device
  * @clk_nb:		Notifier block for clock notify events.
  * @end_timer:		Timer until repeat timeout.
+ * @suspend_timer:	Timer to re-enable protocol.
  * @decoder:		Current decoder settings.
  * @enabled_protocols:	Currently enabled protocols.
  * @clk_hz:		Current core clock rate in Hz.
@@ -214,12 +231,14 @@ enum img_ir_mode {
  * @stopping:		Indicates that decoder is being taken down and timers
  *			should not be restarted.
  * @suspend_irqen:	Saved IRQ enable mask over suspend.
+ * @quirk_suspend_irq:	Saved IRQ enable mask over quirk suspend timer.
  */
 struct img_ir_priv_hw {
 	unsigned int			ct_quirks[4];
 	struct rc_dev			*rdev;
 	struct notifier_block		clk_nb;
 	struct timer_list		end_timer;
+	struct timer_list		suspend_timer;
 	const struct img_ir_decoder	*decoder;
 	u64				enabled_protocols;
 	unsigned long			clk_hz;
@@ -230,6 +249,7 @@ struct img_ir_priv_hw {
 	enum img_ir_mode		mode;
 	bool				stopping;
 	u32				suspend_irqen;
+	u32				quirk_suspend_irq;
 };
 
 static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c
index a60dda8bf706..d3e2fc0bcfe1 100644
--- a/drivers/media/rc/img-ir/img-ir-jvc.c
+++ b/drivers/media/rc/img-ir/img-ir-jvc.c
@@ -12,8 +12,8 @@
 #include "img-ir-hw.h"
 
 /* Convert JVC data to a scancode */
-static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol,
-			       u32 *scancode, u64 enabled_protocols)
+static int img_ir_jvc_scancode(int len, u64 raw, u64 enabled_protocols,
+			       struct img_ir_scancode_req *request)
 {
 	unsigned int cust, data;
 
@@ -23,8 +23,8 @@ static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol,
 	cust = (raw >> 0) & 0xff;
 	data = (raw >> 8) & 0xff;
 
-	*protocol = RC_TYPE_JVC;
-	*scancode = cust << 8 | data;
+	request->protocol = RC_TYPE_JVC;
+	request->scancode = cust << 8 | data;
 	return IMG_IR_SCANCODE;
 }
 
diff --git a/drivers/media/rc/img-ir/img-ir-nec.c b/drivers/media/rc/img-ir/img-ir-nec.c
index 739897549b5b..27a7ea8f1260 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -13,8 +13,8 @@
 #include <linux/bitrev.h>
 
 /* Convert NEC data to a scancode */
-static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
-			       u32 *scancode, u64 enabled_protocols)
+static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols,
+			       struct img_ir_scancode_req *request)
 {
 	unsigned int addr, addr_inv, data, data_inv;
 	/* a repeat code has no data */
@@ -30,23 +30,23 @@ static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
 	if ((data_inv ^ data) != 0xff) {
 		/* 32-bit NEC (used by Apple and TiVo remotes) */
 		/* scan encoding: as transmitted, MSBit = first received bit */
-		*scancode = bitrev8(addr)     << 24 |
-			    bitrev8(addr_inv) << 16 |
-			    bitrev8(data)     <<  8 |
-			    bitrev8(data_inv);
+		request->scancode = bitrev8(addr)     << 24 |
+				bitrev8(addr_inv) << 16 |
+				bitrev8(data)     <<  8 |
+				bitrev8(data_inv);
 	} else if ((addr_inv ^ addr) != 0xff) {
 		/* Extended NEC */
 		/* scan encoding: AAaaDD */
-		*scancode = addr     << 16 |
-			    addr_inv <<  8 |
-			    data;
+		request->scancode = addr     << 16 |
+				addr_inv <<  8 |
+				data;
 	} else {
 		/* Normal NEC */
 		/* scan encoding: AADD */
-		*scancode = addr << 8 |
-			    data;
+		request->scancode = addr << 8 |
+				data;
 	}
-	*protocol = RC_TYPE_NEC;
+	request->protocol = RC_TYPE_NEC;
 	return IMG_IR_SCANCODE;
 }
 
diff --git a/drivers/media/rc/img-ir/img-ir-rc5.c b/drivers/media/rc/img-ir/img-ir-rc5.c
new file mode 100644
index 000000000000..a8a28a377eee
--- /dev/null
+++ b/drivers/media/rc/img-ir/img-ir-rc5.c
@@ -0,0 +1,88 @@
+/*
+ * ImgTec IR Decoder setup for Philips RC-5 protocol.
+ *
+ * Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * 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 "img-ir-hw.h"
+
+/* Convert RC5 data to a scancode */
+static int img_ir_rc5_scancode(int len, u64 raw, u64 enabled_protocols,
+				struct img_ir_scancode_req *request)
+{
+	unsigned int addr, cmd, tgl, start;
+
+	/* Quirk in the decoder shifts everything by 2 to the left. */
+	raw   >>= 2;
+
+	start	=  (raw >> 13)	& 0x01;
+	tgl	=  (raw >> 11)	& 0x01;
+	addr	=  (raw >>  6)	& 0x1f;
+	cmd	=   raw		& 0x3f;
+	/*
+	 * 12th bit is used to extend the command in extended RC5 and has
+	 * no effect on standard RC5.
+	 */
+	cmd	+= ((raw >> 12) & 0x01) ? 0 : 0x40;
+
+	if (!start)
+		return -EINVAL;
+
+	request->protocol = RC_TYPE_RC5;
+	request->scancode = addr << 8 | cmd;
+	request->toggle   = tgl;
+	return IMG_IR_SCANCODE;
+}
+
+/* Convert RC5 scancode to RC5 data filter */
+static int img_ir_rc5_filter(const struct rc_scancode_filter *in,
+				 struct img_ir_filter *out, u64 protocols)
+{
+	/* Not supported by the hw. */
+	return -EINVAL;
+}
+
+/*
+ * RC-5 decoder
+ * see http://www.sbprojects.com/knowledge/ir/rc5.php
+ */
+struct img_ir_decoder img_ir_rc5 = {
+	.type      = RC_BIT_RC5,
+	.control   = {
+		.bitoriend2	= 1,
+		.code_type	= IMG_IR_CODETYPE_BIPHASE,
+		.decodend2	= 1,
+	},
+	/* main timings */
+	.tolerance	= 16,
+	.unit		= 888888, /* 1/36k*32=888.888microseconds */
+	.timings	= {
+		/* 10 symbol */
+		.s10 = {
+			.pulse	= { 1 },
+			.space	= { 1 },
+		},
+
+		/* 11 symbol */
+		.s11 = {
+			.pulse	= { 1 },
+			.space	= { 1 },
+		},
+
+		/* free time */
+		.ft  = {
+			.minlen = 14,
+			.maxlen = 14,
+			.ft_min = 5,
+		},
+	},
+
+	/* scancode logic */
+	.scancode	= img_ir_rc5_scancode,
+	.filter		= img_ir_rc5_filter,
+};
diff --git a/drivers/media/rc/img-ir/img-ir-rc6.c b/drivers/media/rc/img-ir/img-ir-rc6.c
new file mode 100644
index 000000000000..de1e27534968
--- /dev/null
+++ b/drivers/media/rc/img-ir/img-ir-rc6.c
@@ -0,0 +1,117 @@
+/*
+ * ImgTec IR Decoder setup for Philips RC-6 protocol.
+ *
+ * Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * 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 "img-ir-hw.h"
+
+/* Convert RC6 data to a scancode */
+static int img_ir_rc6_scancode(int len, u64 raw, u64 enabled_protocols,
+				struct img_ir_scancode_req *request)
+{
+	unsigned int addr, cmd, mode, trl1, trl2;
+
+	/*
+	 * Due to a side effect of the decoder handling the double length
+	 * Trailer bit, the header information is a bit scrambled, and the
+	 * raw data is shifted incorrectly.
+	 * This workaround effectively recovers the header bits.
+	 *
+	 * The Header field should look like this:
+	 *
+	 * StartBit ModeBit2 ModeBit1 ModeBit0 TrailerBit
+	 *
+	 * But what we get is:
+	 *
+	 * ModeBit2 ModeBit1 ModeBit0 TrailerBit1 TrailerBit2
+	 *
+	 * The start bit is not important to recover the scancode.
+	 */
+
+	raw	>>= 27;
+
+	trl1	= (raw >>  17)	& 0x01;
+	trl2	= (raw >>  16)	& 0x01;
+
+	mode	= (raw >>  18)	& 0x07;
+	addr	= (raw >>   8)	& 0xff;
+	cmd	=  raw		& 0xff;
+
+	/*
+	 * Due to the above explained irregularity the trailer bits cannot
+	 * have the same value.
+	 */
+	if (trl1 == trl2)
+		return -EINVAL;
+
+	/* Only mode 0 supported for now */
+	if (mode)
+		return -EINVAL;
+
+	request->protocol = RC_TYPE_RC6_0;
+	request->scancode = addr << 8 | cmd;
+	request->toggle	  = trl2;
+	return IMG_IR_SCANCODE;
+}
+
+/* Convert RC6 scancode to RC6 data filter */
+static int img_ir_rc6_filter(const struct rc_scancode_filter *in,
+				 struct img_ir_filter *out, u64 protocols)
+{
+	/* Not supported by the hw. */
+	return -EINVAL;
+}
+
+/*
+ * RC-6 decoder
+ * see http://www.sbprojects.com/knowledge/ir/rc6.php
+ */
+struct img_ir_decoder img_ir_rc6 = {
+	.type		= RC_BIT_RC6_0,
+	.control	= {
+		.bitorien	= 1,
+		.code_type	= IMG_IR_CODETYPE_BIPHASE,
+		.decoden	= 1,
+		.decodinpol	= 1,
+	},
+	/* main timings */
+	.tolerance	= 20,
+	/*
+	 * Due to a quirk in the img-ir decoder, default header values do
+	 * not work, the values described below were extracted from
+	 * successful RTL test cases.
+	 */
+	.timings	= {
+		/* leader symbol */
+		.ldr = {
+			.pulse	= { 650 },
+			.space	= { 660 },
+		},
+		/* 0 symbol */
+		.s00 = {
+			.pulse	= { 370 },
+			.space	= { 370 },
+		},
+		/* 01 symbol */
+		.s01 = {
+			.pulse	= { 370 },
+			.space	= { 370 },
+		},
+		/* free time */
+		.ft  = {
+			.minlen = 21,
+			.maxlen = 21,
+			.ft_min = 2666,	/* 2.666 ms */
+		},
+	},
+
+	/* scancode logic */
+	.scancode	= img_ir_rc6_scancode,
+	.filter		= img_ir_rc6_filter,
+};
diff --git a/drivers/media/rc/img-ir/img-ir-sanyo.c b/drivers/media/rc/img-ir/img-ir-sanyo.c
index 6b0653ecdf5a..f394994ffc22 100644
--- a/drivers/media/rc/img-ir/img-ir-sanyo.c
+++ b/drivers/media/rc/img-ir/img-ir-sanyo.c
@@ -23,8 +23,8 @@
 #include "img-ir-hw.h"
 
 /* Convert Sanyo data to a scancode */
-static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
-				 u32 *scancode, u64 enabled_protocols)
+static int img_ir_sanyo_scancode(int len, u64 raw, u64 enabled_protocols,
+				 struct img_ir_scancode_req *request)
 {
 	unsigned int addr, addr_inv, data, data_inv;
 	/* a repeat code has no data */
@@ -44,8 +44,8 @@ static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
 		return -EINVAL;
 
 	/* Normal Sanyo */
-	*protocol = RC_TYPE_SANYO;
-	*scancode = addr << 8 | data;
+	request->protocol = RC_TYPE_SANYO;
+	request->scancode = addr << 8 | data;
 	return IMG_IR_SCANCODE;
 }
 
diff --git a/drivers/media/rc/img-ir/img-ir-sharp.c b/drivers/media/rc/img-ir/img-ir-sharp.c
index 3300a38802ac..fe5acc4f030e 100644
--- a/drivers/media/rc/img-ir/img-ir-sharp.c
+++ b/drivers/media/rc/img-ir/img-ir-sharp.c
@@ -12,8 +12,8 @@
 #include "img-ir-hw.h"
 
 /* Convert Sharp data to a scancode */
-static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
-				 u32 *scancode, u64 enabled_protocols)
+static int img_ir_sharp_scancode(int len, u64 raw, u64 enabled_protocols,
+				 struct img_ir_scancode_req *request)
 {
 	unsigned int addr, cmd, exp, chk;
 
@@ -32,8 +32,8 @@ static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
 		/* probably the second half of the message */
 		return -EINVAL;
 
-	*protocol = RC_TYPE_SHARP;
-	*scancode = addr << 8 | cmd;
+	request->protocol = RC_TYPE_SHARP;
+	request->scancode = addr << 8 | cmd;
 	return IMG_IR_SCANCODE;
 }
 
diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c
index 3a0f17b0752c..7f7375f82ed6 100644
--- a/drivers/media/rc/img-ir/img-ir-sony.c
+++ b/drivers/media/rc/img-ir/img-ir-sony.c
@@ -12,8 +12,8 @@
 #include "img-ir-hw.h"
 
 /* Convert Sony data to a scancode */
-static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
-				u32 *scancode, u64 enabled_protocols)
+static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols,
+				struct img_ir_scancode_req *request)
 {
 	unsigned int dev, subdev, func;
 
@@ -25,7 +25,7 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
 		raw    >>= 7;
 		dev    = raw & 0x1f;	/* next 5 bits */
 		subdev = 0;
-		*protocol = RC_TYPE_SONY12;
+		request->protocol = RC_TYPE_SONY12;
 		break;
 	case 15:
 		if (!(enabled_protocols & RC_BIT_SONY15))
@@ -34,7 +34,7 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
 		raw    >>= 7;
 		dev    = raw & 0xff;	/* next 8 bits */
 		subdev = 0;
-		*protocol = RC_TYPE_SONY15;
+		request->protocol = RC_TYPE_SONY15;
 		break;
 	case 20:
 		if (!(enabled_protocols & RC_BIT_SONY20))
@@ -44,12 +44,12 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
 		dev    = raw & 0x1f;	/* next 5 bits */
 		raw    >>= 5;
 		subdev = raw & 0xff;	/* next 8 bits */
-		*protocol = RC_TYPE_SONY20;
+		request->protocol = RC_TYPE_SONY20;
 		break;
 	default:
 		return -EINVAL;
 	}
-	*scancode = dev << 16 | subdev << 8 | func;
+	request->scancode = dev << 16 | subdev << 8 | func;
 	return IMG_IR_SCANCODE;
 }
 
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 1e0545a67959..4de0e85af805 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -553,14 +553,14 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 	if (!ir->attached)
 		return POLLERR;
 
-	poll_wait(file, &ir->buf->wait_poll, wait);
+	if (ir->buf) {
+		poll_wait(file, &ir->buf->wait_poll, wait);
 
-	if (ir->buf)
 		if (lirc_buffer_empty(ir->buf))
 			ret = 0;
 		else
 			ret = POLLIN | POLLRDNORM;
-	else
+	} else
 		ret = POLLERR;
 
 	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 86ffcd54339e..f8c5e47a30aa 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1021,16 +1021,16 @@ static ssize_t store_protocols(struct device *device,
 		goto out;
 	}
 
-	if (new_protocols == old_protocols) {
-		rc = len;
-		goto out;
+	if (new_protocols != old_protocols) {
+		*current_protocols = new_protocols;
+		IR_dprintk(1, "Protocols changed to 0x%llx\n",
+			   (long long)new_protocols);
 	}
 
-	*current_protocols = new_protocols;
-	IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols);
-
 	/*
-	 * If the protocol is changed the filter needs updating.
+	 * If a protocol change was attempted the filter may need updating, even
+	 * if the actual protocol mask hasn't changed (since the driver may have
+	 * cleared the filter).
 	 * Try setting the same filter with the new protocol (if any).
 	 * Fall back to clearing the filter.
 	 */
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index 340f7f51eed4..7830aef3db45 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
+#include <linux/reset.h>
 #include <media/rc-core.h>
 
 #define SUNXI_IR_DEV "sunxi-ir"
@@ -55,12 +56,12 @@
 #define REG_RXINT_RAI_EN		BIT(4)
 
 /* Rx FIFO available byte level */
-#define REG_RXINT_RAL(val)    (((val) << 8) & (GENMASK(11, 8)))
+#define REG_RXINT_RAL(val)    ((val) << 8)
 
 /* Rx Interrupt Status */
 #define SUNXI_IR_RXSTA_REG    0x30
 /* RX FIFO Get Available Counter */
-#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (GENMASK(5, 0)))
+#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (ir->fifo_size * 2 - 1))
 /* Clear all interrupt status value */
 #define REG_RXSTA_CLEARALL    0xff
 
@@ -71,10 +72,6 @@
 /* CIR_REG register idle threshold */
 #define REG_CIR_ITHR(val)    (((val) << 8) & (GENMASK(15, 8)))
 
-/* Hardware supported fifo size */
-#define SUNXI_IR_FIFO_SIZE    16
-/* How many messages in FIFO trigger IRQ */
-#define TRIGGER_LEVEL         8
 /* Required frequency for IR0 or IR1 clock in CIR mode */
 #define SUNXI_IR_BASE_CLK     8000000
 /* Frequency after IR internal divider  */
@@ -93,8 +90,10 @@ struct sunxi_ir {
 	struct rc_dev   *rc;
 	void __iomem    *base;
 	int             irq;
+	int		fifo_size;
 	struct clk      *clk;
 	struct clk      *apb_clk;
+	struct reset_control *rst;
 	const char      *map_name;
 };
 
@@ -113,11 +112,11 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
 	/* clean all pending statuses */
 	writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
 
-	if (status & REG_RXINT_RAI_EN) {
+	if (status & (REG_RXINT_RAI_EN | REG_RXINT_RPEI_EN)) {
 		/* How many messages in fifo */
 		rc  = REG_RXSTA_GET_AC(status);
 		/* Sanity check */
-		rc = rc > SUNXI_IR_FIFO_SIZE ? SUNXI_IR_FIFO_SIZE : rc;
+		rc = rc > ir->fifo_size ? ir->fifo_size : rc;
 		/* If we have data */
 		for (cnt = 0; cnt < rc; cnt++) {
 			/* for each bit in fifo */
@@ -154,6 +153,11 @@ static int sunxi_ir_probe(struct platform_device *pdev)
 	if (!ir)
 		return -ENOMEM;
 
+	if (of_device_is_compatible(dn, "allwinner,sun5i-a13-ir"))
+		ir->fifo_size = 64;
+	else
+		ir->fifo_size = 16;
+
 	/* Clock */
 	ir->apb_clk = devm_clk_get(dev, "apb");
 	if (IS_ERR(ir->apb_clk)) {
@@ -166,15 +170,29 @@ static int sunxi_ir_probe(struct platform_device *pdev)
 		return PTR_ERR(ir->clk);
 	}
 
+	/* Reset (optional) */
+	ir->rst = devm_reset_control_get_optional(dev, NULL);
+	if (IS_ERR(ir->rst)) {
+		ret = PTR_ERR(ir->rst);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+		ir->rst = NULL;
+	} else {
+		ret = reset_control_deassert(ir->rst);
+		if (ret)
+			return ret;
+	}
+
 	ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK);
 	if (ret) {
 		dev_err(dev, "set ir base clock failed!\n");
-		return ret;
+		goto exit_reset_assert;
 	}
 
 	if (clk_prepare_enable(ir->apb_clk)) {
 		dev_err(dev, "try to enable apb_ir_clk failed\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto exit_reset_assert;
 	}
 
 	if (clk_prepare_enable(ir->clk)) {
@@ -255,7 +273,7 @@ static int sunxi_ir_probe(struct platform_device *pdev)
 	 * level
 	 */
 	writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN |
-	       REG_RXINT_RAI_EN | REG_RXINT_RAL(TRIGGER_LEVEL - 1),
+	       REG_RXINT_RAI_EN | REG_RXINT_RAL(ir->fifo_size / 2 - 1),
 	       ir->base + SUNXI_IR_RXINT_REG);
 
 	/* Enable IR Module */
@@ -271,6 +289,9 @@ exit_clkdisable_clk:
 	clk_disable_unprepare(ir->clk);
 exit_clkdisable_apb_clk:
 	clk_disable_unprepare(ir->apb_clk);
+exit_reset_assert:
+	if (ir->rst)
+		reset_control_assert(ir->rst);
 
 	return ret;
 }
@@ -282,6 +303,8 @@ static int sunxi_ir_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(ir->clk);
 	clk_disable_unprepare(ir->apb_clk);
+	if (ir->rst)
+		reset_control_assert(ir->rst);
 
 	spin_lock_irqsave(&ir->ir_lock, flags);
 	/* disable IR IRQ */
@@ -298,6 +321,7 @@ static int sunxi_ir_remove(struct platform_device *pdev)
 
 static const struct of_device_id sunxi_ir_match[] = {
 	{ .compatible = "allwinner,sun4i-a10-ir", },
+	{ .compatible = "allwinner,sun5i-a13-ir", },
 	{},
 };
 
diff --git a/drivers/media/tuners/mt20xx.c b/drivers/media/tuners/mt20xx.c
index 0e74e97e0d1a..9e031040c13f 100644
--- a/drivers/media/tuners/mt20xx.c
+++ b/drivers/media/tuners/mt20xx.c
@@ -660,11 +660,3 @@ EXPORT_SYMBOL_GPL(microtune_attach);
 MODULE_DESCRIPTION("Microtune tuner driver");
 MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
 MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/mt2131.c b/drivers/media/tuners/mt2131.c
index f83b0c1ea6c8..6e2cdd2b6175 100644
--- a/drivers/media/tuners/mt2131.c
+++ b/drivers/media/tuners/mt2131.c
@@ -294,8 +294,3 @@ EXPORT_SYMBOL(mt2131_attach);
 MODULE_AUTHOR("Steven Toth");
 MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/tuners/mt2131.h b/drivers/media/tuners/mt2131.h
index 09ceaf68e47c..837c854b9c65 100644
--- a/drivers/media/tuners/mt2131.h
+++ b/drivers/media/tuners/mt2131.h
@@ -47,8 +47,3 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
 #endif /* CONFIG_MEDIA_TUNER_MT2131 */
 
 #endif /* __MT2131_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/tuners/mt2131_priv.h b/drivers/media/tuners/mt2131_priv.h
index 62aeedf5c550..91283b599cb3 100644
--- a/drivers/media/tuners/mt2131_priv.h
+++ b/drivers/media/tuners/mt2131_priv.h
@@ -41,8 +41,3 @@ struct mt2131_priv {
 };
 
 #endif /* __MT2131_PRIV_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/tuners/mxl5007t.c b/drivers/media/tuners/mxl5007t.c
index 1810ad66888e..f4ae04c3328a 100644
--- a/drivers/media/tuners/mxl5007t.c
+++ b/drivers/media/tuners/mxl5007t.c
@@ -938,11 +938,3 @@ MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.2");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/mxl5007t.h b/drivers/media/tuners/mxl5007t.h
index 37b0942e2385..ae7037d681c5 100644
--- a/drivers/media/tuners/mxl5007t.h
+++ b/drivers/media/tuners/mxl5007t.h
@@ -93,12 +93,3 @@ static inline struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
 #endif
 
 #endif /* __MXL5007T_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 2180de9d654a..fcf139dfdec6 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -19,16 +19,17 @@
 static const struct dvb_tuner_ops si2157_ops;
 
 /* execute firmware command */
-static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
+static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
 {
+	struct si2157_dev *dev = i2c_get_clientdata(client);
 	int ret;
 	unsigned long timeout;
 
-	mutex_lock(&s->i2c_mutex);
+	mutex_lock(&dev->i2c_mutex);
 
 	if (cmd->wlen) {
 		/* write cmd and args for firmware */
-		ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
+		ret = i2c_master_send(client, cmd->args, cmd->wlen);
 		if (ret < 0) {
 			goto err_mutex_unlock;
 		} else if (ret != cmd->wlen) {
@@ -42,7 +43,7 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
 		#define TIMEOUT 80
 		timeout = jiffies + msecs_to_jiffies(TIMEOUT);
 		while (!time_after(jiffies, timeout)) {
-			ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
+			ret = i2c_master_recv(client, cmd->args, cmd->rlen);
 			if (ret < 0) {
 				goto err_mutex_unlock;
 			} else if (ret != cmd->rlen) {
@@ -55,7 +56,7 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
 				break;
 		}
 
-		dev_dbg(&s->client->dev, "cmd execution took %d ms\n",
+		dev_dbg(&client->dev, "cmd execution took %d ms\n",
 				jiffies_to_msecs(jiffies) -
 				(jiffies_to_msecs(timeout) - TIMEOUT));
 
@@ -65,35 +66,32 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
 		}
 	}
 
-	ret = 0;
+	mutex_unlock(&dev->i2c_mutex);
+	return 0;
 
 err_mutex_unlock:
-	mutex_unlock(&s->i2c_mutex);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	mutex_unlock(&dev->i2c_mutex);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2157_init(struct dvb_frontend *fe)
 {
-	struct si2157 *s = fe->tuner_priv;
+	struct i2c_client *client = fe->tuner_priv;
+	struct si2157_dev *dev = i2c_get_clientdata(client);
 	int ret, len, remaining;
 	struct si2157_cmd cmd;
-	const struct firmware *fw = NULL;
-	u8 *fw_file;
+	const struct firmware *fw;
+	const char *fw_name;
 	unsigned int chip_id;
 
-	dev_dbg(&s->client->dev, "\n");
+	dev_dbg(&client->dev, "\n");
 
-	if (s->fw_loaded)
+	if (dev->fw_loaded)
 		goto warm;
 
 	/* power up */
-	if (s->chiptype == SI2157_CHIPTYPE_SI2146) {
+	if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
 		memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
 		cmd.wlen = 9;
 	} else {
@@ -101,7 +99,7 @@ static int si2157_init(struct dvb_frontend *fe)
 		cmd.wlen = 15;
 	}
 	cmd.rlen = 1;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -109,7 +107,7 @@ static int si2157_init(struct dvb_frontend *fe)
 	memcpy(cmd.args, "\x02", 1);
 	cmd.wlen = 1;
 	cmd.rlen = 13;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -125,121 +123,133 @@ static int si2157_init(struct dvb_frontend *fe)
 	switch (chip_id) {
 	case SI2158_A20:
 	case SI2148_A20:
-		fw_file = SI2158_A20_FIRMWARE;
+		fw_name = SI2158_A20_FIRMWARE;
 		break;
 	case SI2157_A30:
 	case SI2147_A30:
 	case SI2146_A10:
-		goto skip_fw_download;
+		fw_name = NULL;
+		break;
 	default:
-		dev_err(&s->client->dev,
-				"unknown chip version Si21%d-%c%c%c\n",
+		dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
 				cmd.args[2], cmd.args[1],
 				cmd.args[3], cmd.args[4]);
 		ret = -EINVAL;
 		goto err;
 	}
 
-	/* cold state - try to download firmware */
-	dev_info(&s->client->dev, "found a '%s' in cold state\n",
-			si2157_ops.info.name);
+	dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
+			cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
+
+	if (fw_name == NULL)
+		goto skip_fw_download;
 
 	/* request the firmware, this will block and timeout */
-	ret = request_firmware(&fw, fw_file, &s->client->dev);
+	ret = request_firmware(&fw, fw_name, &client->dev);
 	if (ret) {
-		dev_err(&s->client->dev, "firmware file '%s' not found\n",
-				fw_file);
+		dev_err(&client->dev, "firmware file '%s' not found\n",
+				fw_name);
 		goto err;
 	}
 
 	/* firmware should be n chunks of 17 bytes */
 	if (fw->size % 17 != 0) {
-		dev_err(&s->client->dev, "firmware file '%s' is invalid\n",
-				fw_file);
+		dev_err(&client->dev, "firmware file '%s' is invalid\n",
+				fw_name);
 		ret = -EINVAL;
-		goto fw_release_exit;
+		goto err_release_firmware;
 	}
 
-	dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
-			fw_file);
+	dev_info(&client->dev, "downloading firmware from file '%s'\n",
+			fw_name);
 
 	for (remaining = fw->size; remaining > 0; remaining -= 17) {
 		len = fw->data[fw->size - remaining];
 		memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
 		cmd.wlen = len;
 		cmd.rlen = 1;
-		ret = si2157_cmd_execute(s, &cmd);
+		ret = si2157_cmd_execute(client, &cmd);
 		if (ret) {
-			dev_err(&s->client->dev,
-					"firmware download failed=%d\n",
+			dev_err(&client->dev, "firmware download failed %d\n",
 					ret);
-			goto fw_release_exit;
+			goto err_release_firmware;
 		}
 	}
 
 	release_firmware(fw);
-	fw = NULL;
 
 skip_fw_download:
 	/* reboot the tuner with new firmware? */
 	memcpy(cmd.args, "\x01\x01", 2);
 	cmd.wlen = 2;
 	cmd.rlen = 1;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	s->fw_loaded = true;
+	/* query firmware version */
+	memcpy(cmd.args, "\x11", 1);
+	cmd.wlen = 1;
+	cmd.rlen = 10;
+	ret = si2157_cmd_execute(client, &cmd);
+	if (ret)
+		goto err;
+
+	dev_info(&client->dev, "firmware version: %c.%c.%d\n",
+			cmd.args[6], cmd.args[7], cmd.args[8]);
+
+	dev->fw_loaded = true;
 
 warm:
-	s->active = true;
+	dev->active = true;
 	return 0;
 
-fw_release_exit:
+err_release_firmware:
 	release_firmware(fw);
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2157_sleep(struct dvb_frontend *fe)
 {
-	struct si2157 *s = fe->tuner_priv;
+	struct i2c_client *client = fe->tuner_priv;
+	struct si2157_dev *dev = i2c_get_clientdata(client);
 	int ret;
 	struct si2157_cmd cmd;
 
-	dev_dbg(&s->client->dev, "\n");
+	dev_dbg(&client->dev, "\n");
 
-	s->active = false;
+	dev->active = false;
 
 	/* standby */
 	memcpy(cmd.args, "\x16\x00", 2);
 	cmd.wlen = 2;
 	cmd.rlen = 1;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	return 0;
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int si2157_set_params(struct dvb_frontend *fe)
 {
-	struct si2157 *s = fe->tuner_priv;
+	struct i2c_client *client = fe->tuner_priv;
+	struct si2157_dev *dev = i2c_get_clientdata(client);
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
 	struct si2157_cmd cmd;
 	u8 bandwidth, delivery_system;
 
-	dev_dbg(&s->client->dev,
+	dev_dbg(&client->dev,
 			"delivery_system=%d frequency=%u bandwidth_hz=%u\n",
-			c->delivery_system, c->frequency,
-			c->bandwidth_hz);
+			c->delivery_system, c->frequency, c->bandwidth_hz);
 
-	if (!s->active) {
+	if (!dev->active) {
 		ret = -EAGAIN;
 		goto err;
 	}
@@ -274,21 +284,21 @@ static int si2157_set_params(struct dvb_frontend *fe)
 
 	memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
 	cmd.args[4] = delivery_system | bandwidth;
-	if (s->inversion)
+	if (dev->inversion)
 		cmd.args[5] = 0x01;
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
-	if (s->chiptype == SI2157_CHIPTYPE_SI2146)
+	if (dev->chiptype == SI2157_CHIPTYPE_SI2146)
 		memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
 	else
 		memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
@@ -300,13 +310,13 @@ static int si2157_set_params(struct dvb_frontend *fe)
 	cmd.args[7] = (c->frequency >> 24) & 0xff;
 	cmd.wlen = 8;
 	cmd.rlen = 1;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
 		goto err;
 
 	return 0;
 err:
-	dev_dbg(&s->client->dev, "failed=%d\n", ret);
+	dev_dbg(&client->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -334,70 +344,67 @@ static int si2157_probe(struct i2c_client *client,
 {
 	struct si2157_config *cfg = client->dev.platform_data;
 	struct dvb_frontend *fe = cfg->fe;
-	struct si2157 *s;
+	struct si2157_dev *dev;
 	struct si2157_cmd cmd;
 	int ret;
 
-	s = kzalloc(sizeof(struct si2157), GFP_KERNEL);
-	if (!s) {
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
 		ret = -ENOMEM;
 		dev_err(&client->dev, "kzalloc() failed\n");
 		goto err;
 	}
 
-	s->client = client;
-	s->fe = cfg->fe;
-	s->inversion = cfg->inversion;
-	s->fw_loaded = false;
-	s->chiptype = (u8)id->driver_data;
-	mutex_init(&s->i2c_mutex);
+	i2c_set_clientdata(client, dev);
+	dev->fe = cfg->fe;
+	dev->inversion = cfg->inversion;
+	dev->fw_loaded = false;
+	dev->chiptype = (u8)id->driver_data;
+	mutex_init(&dev->i2c_mutex);
 
 	/* check if the tuner is there */
 	cmd.wlen = 0;
 	cmd.rlen = 1;
-	ret = si2157_cmd_execute(s, &cmd);
+	ret = si2157_cmd_execute(client, &cmd);
 	if (ret)
-		goto err;
+		goto err_kfree;
 
-	fe->tuner_priv = s;
-	memcpy(&fe->ops.tuner_ops, &si2157_ops,
-			sizeof(struct dvb_tuner_ops));
+	memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
+	fe->tuner_priv = client;
 
-	i2c_set_clientdata(client, s);
-
-	dev_info(&s->client->dev,
-			"Silicon Labs %s successfully attached\n",
-			s->chiptype == SI2157_CHIPTYPE_SI2146 ?
+	dev_info(&client->dev, "Silicon Labs %s successfully attached\n",
+			dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
 			"Si2146" : "Si2147/2148/2157/2158");
 
 	return 0;
+
+err_kfree:
+	kfree(dev);
 err:
 	dev_dbg(&client->dev, "failed=%d\n", ret);
-	kfree(s);
-
 	return ret;
 }
 
 static int si2157_remove(struct i2c_client *client)
 {
-	struct si2157 *s = i2c_get_clientdata(client);
-	struct dvb_frontend *fe = s->fe;
+	struct si2157_dev *dev = i2c_get_clientdata(client);
+	struct dvb_frontend *fe = dev->fe;
 
 	dev_dbg(&client->dev, "\n");
 
 	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
 	fe->tuner_priv = NULL;
-	kfree(s);
+	kfree(dev);
 
 	return 0;
 }
 
-static const struct i2c_device_id si2157_id[] = {
-	{"si2157", 0},
-	{"si2146", 1},
+static const struct i2c_device_id si2157_id_table[] = {
+	{"si2157", SI2157_CHIPTYPE_SI2157},
+	{"si2146", SI2157_CHIPTYPE_SI2146},
 	{}
 };
-MODULE_DEVICE_TABLE(i2c, si2157_id);
+MODULE_DEVICE_TABLE(i2c, si2157_id_table);
 
 static struct i2c_driver si2157_driver = {
 	.driver = {
@@ -406,7 +413,7 @@ static struct i2c_driver si2157_driver = {
 	},
 	.probe		= si2157_probe,
 	.remove		= si2157_remove,
-	.id_table	= si2157_id,
+	.id_table	= si2157_id_table,
 };
 
 module_i2c_driver(si2157_driver);
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index d6e07cdd2a07..7aa53bce5593 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -21,9 +21,8 @@
 #include "si2157.h"
 
 /* state struct */
-struct si2157 {
+struct si2157_dev {
 	struct mutex i2c_mutex;
-	struct i2c_client *client;
 	struct dvb_frontend *fe;
 	bool active;
 	bool fw_loaded;
diff --git a/drivers/media/tuners/tda18271-fe.c b/drivers/media/tuners/tda18271-fe.c
index 4995b890c164..f8620741bb5f 100644
--- a/drivers/media/tuners/tda18271-fe.c
+++ b/drivers/media/tuners/tda18271-fe.c
@@ -1355,11 +1355,3 @@ MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.4");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/tda18271-maps.c b/drivers/media/tuners/tda18271-maps.c
index b62e925f643f..1e89dd93c4bb 100644
--- a/drivers/media/tuners/tda18271-maps.c
+++ b/drivers/media/tuners/tda18271-maps.c
@@ -1305,11 +1305,3 @@ int tda18271_assign_map_layout(struct dvb_frontend *fe)
 
 	return ret;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/tda18271-priv.h b/drivers/media/tuners/tda18271-priv.h
index b36a7b754772..cc80f544af34 100644
--- a/drivers/media/tuners/tda18271-priv.h
+++ b/drivers/media/tuners/tda18271-priv.h
@@ -226,11 +226,3 @@ extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq);
 extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq);
 
 #endif /* __TDA18271_PRIV_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/tda827x.c b/drivers/media/tuners/tda827x.c
index 73453a255cdc..edcb4a723aa1 100644
--- a/drivers/media/tuners/tda827x.c
+++ b/drivers/media/tuners/tda827x.c
@@ -907,11 +907,3 @@ MODULE_DESCRIPTION("DVB TDA827x driver");
 MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
index ab4106c17b4c..998e82bba9c0 100644
--- a/drivers/media/tuners/tda8290.c
+++ b/drivers/media/tuners/tda8290.c
@@ -881,11 +881,3 @@ EXPORT_SYMBOL_GPL(tda829x_probe);
 MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
 MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
 MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/tda9887.c b/drivers/media/tuners/tda9887.c
index 9823248d743f..56be6c29399b 100644
--- a/drivers/media/tuners/tda9887.c
+++ b/drivers/media/tuners/tda9887.c
@@ -707,11 +707,3 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
 EXPORT_SYMBOL_GPL(tda9887_attach);
 
 MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/tuners/tuner-simple.c b/drivers/media/tuners/tuner-simple.c
index ca274c2d8c70..8e9ce144da9a 100644
--- a/drivers/media/tuners/tuner-simple.c
+++ b/drivers/media/tuners/tuner-simple.c
@@ -1148,11 +1148,3 @@ EXPORT_SYMBOL_GPL(simple_tuner_attach);
 MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
 MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
 MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig
index 1d410ac8f9a8..78b797e0b434 100644
--- a/drivers/media/usb/au0828/Kconfig
+++ b/drivers/media/usb/au0828/Kconfig
@@ -4,7 +4,7 @@ config VIDEO_AU0828
 	depends on I2C && INPUT && DVB_CORE && USB
 	select I2C_ALGOBIT
 	select VIDEO_TVEEPROM
-	select VIDEOBUF_VMALLOC
+	select VIDEOBUF2_VMALLOC
 	select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index da87f1cc31a9..edc27355f271 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -44,7 +44,7 @@ static void hvr950q_cs5340_audio(void *priv, int enable)
 struct au0828_board au0828_boards[] = {
 	[AU0828_BOARD_UNKNOWN] = {
 		.name	= "Unknown board",
-		.tuner_type = UNSET,
+		.tuner_type = -1U,
 		.tuner_addr = ADDR_UNSET,
 	},
 	[AU0828_BOARD_HAUPPAUGE_HVR850] = {
diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
index 932d24f42b24..f67247cf1a5a 100644
--- a/drivers/media/usb/au0828/au0828-vbi.c
+++ b/drivers/media/usb/au0828/au0828-vbi.c
@@ -28,111 +28,67 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 
-static unsigned int vbibufs = 5;
-module_param(vbibufs, int, 0644);
-MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
-
 /* ------------------------------------------------------------------ */
 
-static void
-free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
+static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+			   unsigned int *nbuffers, unsigned int *nplanes,
+			   unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct au0828_fh     *fh  = vq->priv_data;
-	struct au0828_dev    *dev = fh->dev;
-	unsigned long flags = 0;
-	if (in_interrupt())
-		BUG();
-
-	/* We used to wait for the buffer to finish here, but this didn't work
-	   because, as we were keeping the state as VIDEOBUF_QUEUED,
-	   videobuf_queue_cancel marked it as finished for us.
-	   (Also, it could wedge forever if the hardware was misconfigured.)
-
-	   This should be safe; by the time we get here, the buffer isn't
-	   queued anymore. If we ever start marking the buffers as
-	   VIDEOBUF_ACTIVE, it won't be, though.
-	*/
-	spin_lock_irqsave(&dev->slock, flags);
-	if (dev->isoc_ctl.vbi_buf == buf)
-		dev->isoc_ctl.vbi_buf = NULL;
-	spin_unlock_irqrestore(&dev->slock, flags);
+	struct au0828_dev *dev = vb2_get_drv_priv(vq);
+	unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
+	unsigned long size;
 
-	videobuf_vmalloc_free(&buf->vb);
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int
-vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-	struct au0828_fh     *fh  = q->priv_data;
-	struct au0828_dev    *dev = fh->dev;
+	size = fmt ? (fmt->fmt.vbi.samples_per_line *
+		(fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size;
+	if (size < img_size)
+		return -EINVAL;
 
-	*size = dev->vbi_width * dev->vbi_height * 2;
+	*nplanes = 1;
+	sizes[0] = size;
 
-	if (0 == *count)
-		*count = vbibufs;
-	if (*count < 2)
-		*count = 2;
-	if (*count > 32)
-		*count = 32;
 	return 0;
 }
 
-static int
-vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-	    enum v4l2_field field)
+static int vbi_buffer_prepare(struct vb2_buffer *vb)
 {
-	struct au0828_fh     *fh  = q->priv_data;
-	struct au0828_dev    *dev = fh->dev;
+	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
-	int                  rc = 0;
+	unsigned long size;
 
-	buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
+	size = dev->vbi_width * dev->vbi_height * 2;
 
-	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+	if (vb2_plane_size(vb, 0) < size) {
+		pr_err("%s data will not fit into plane (%lu < %lu)\n",
+			__func__, vb2_plane_size(vb, 0), size);
 		return -EINVAL;
-
-	buf->vb.width  = dev->vbi_width;
-	buf->vb.height = dev->vbi_height;
-	buf->vb.field  = field;
-
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		rc = videobuf_iolock(q, &buf->vb, NULL);
-		if (rc < 0)
-			goto fail;
 	}
+	vb2_set_plane_payload(&buf->vb, 0, size);
 
-	buf->vb.state = VIDEOBUF_PREPARED;
 	return 0;
-
-fail:
-	free_buffer(q, buf);
-	return rc;
 }
 
 static void
-vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-	struct au0828_buffer    *buf     = container_of(vb,
-							struct au0828_buffer,
-							vb);
-	struct au0828_fh        *fh      = vq->priv_data;
-	struct au0828_dev       *dev     = fh->dev;
-	struct au0828_dmaqueue  *vbiq    = &dev->vbiq;
-
-	buf->vb.state = VIDEOBUF_QUEUED;
-	list_add_tail(&buf->vb.queue, &vbiq->active);
-}
-
-static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+vbi_buffer_queue(struct vb2_buffer *vb)
 {
+	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
-	free_buffer(q, buf);
+	struct au0828_dmaqueue *vbiq = &dev->vbiq;
+	unsigned long flags = 0;
+
+	buf->mem = vb2_plane_vaddr(vb, 0);
+	buf->length = vb2_plane_size(vb, 0);
+
+	spin_lock_irqsave(&dev->slock, flags);
+	list_add_tail(&buf->list, &vbiq->active);
+	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-struct videobuf_queue_ops au0828_vbi_qops = {
-	.buf_setup    = vbi_setup,
-	.buf_prepare  = vbi_prepare,
-	.buf_queue    = vbi_queue,
-	.buf_release  = vbi_release,
+struct vb2_ops au0828_vbi_qops = {
+	.queue_setup     = vbi_queue_setup,
+	.buf_prepare     = vbi_buffer_prepare,
+	.buf_queue       = vbi_buffer_queue,
+	.start_streaming = au0828_start_analog_streaming,
+	.stop_streaming  = au0828_stop_vbi_streaming,
+	.wait_prepare    = vb2_ops_wait_prepare,
+	.wait_finish     = vb2_ops_wait_finish,
 };
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 5f337b118bff..a27cb5fcdef8 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -22,7 +22,6 @@
 
 /* Developer Notes:
  *
- * VBI support is not yet working
  * The hardware scaler supported is unimplemented
  * AC97 audio support is unimplemented (only i2s audio mode)
  *
@@ -219,9 +218,6 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
 
 	au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
 
-	/* De-allocates all pending stuff */
-	au0828_uninit_isoc(dev);
-
 	dev->isoc_ctl.isoc_copy = isoc_copy;
 	dev->isoc_ctl.num_bufs = num_bufs;
 
@@ -285,8 +281,6 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
 		}
 	}
 
-	init_waitqueue_head(&dma_q->wq);
-
 	/* submit urbs and enables IRQ */
 	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
 		rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
@@ -309,16 +303,12 @@ static inline void buffer_filled(struct au0828_dev *dev,
 				  struct au0828_buffer *buf)
 {
 	/* Advice that buffer was filled */
-	au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-
-	buf->vb.state = VIDEOBUF_DONE;
-	buf->vb.field_count++;
-	v4l2_get_timestamp(&buf->vb.ts);
+	au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
 
-	dev->isoc_ctl.buf = NULL;
-
-	list_del(&buf->vb.queue);
-	wake_up(&buf->vb.done);
+	buf->vb.v4l2_buf.sequence = dev->frame_count++;
+	buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
+	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
 }
 
 static inline void vbi_buffer_filled(struct au0828_dev *dev,
@@ -326,16 +316,12 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev,
 				     struct au0828_buffer *buf)
 {
 	/* Advice that buffer was filled */
-	au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-
-	buf->vb.state = VIDEOBUF_DONE;
-	buf->vb.field_count++;
-	v4l2_get_timestamp(&buf->vb.ts);
+	au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
 
-	dev->isoc_ctl.vbi_buf = NULL;
-
-	list_del(&buf->vb.queue);
-	wake_up(&buf->vb.done);
+	buf->vb.v4l2_buf.sequence = dev->vbi_frame_count++;
+	buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
+	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
 }
 
 /*
@@ -354,8 +340,8 @@ static void au0828_copy_video(struct au0828_dev *dev,
 	if (len == 0)
 		return;
 
-	if (dma_q->pos + len > buf->vb.size)
-		len = buf->vb.size - dma_q->pos;
+	if (dma_q->pos + len > buf->length)
+		len = buf->length - dma_q->pos;
 
 	startread = p;
 	remain = len;
@@ -373,11 +359,11 @@ static void au0828_copy_video(struct au0828_dev *dev,
 	lencopy = bytesperline - currlinedone;
 	lencopy = lencopy > remain ? remain : lencopy;
 
-	if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+	if ((char *)startwrite + lencopy > (char *)outp + buf->length) {
 		au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
 			       ((char *)startwrite + lencopy) -
-			       ((char *)outp + buf->vb.size));
-		remain = (char *)outp + buf->vb.size - (char *)startwrite;
+			       ((char *)outp + buf->length));
+		remain = (char *)outp + buf->length - (char *)startwrite;
 		lencopy = remain;
 	}
 	if (lencopy <= 0)
@@ -395,11 +381,11 @@ static void au0828_copy_video(struct au0828_dev *dev,
 			lencopy = bytesperline;
 
 		if ((char *)startwrite + lencopy > (char *)outp +
-		    buf->vb.size) {
+		    buf->length) {
 			au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
 				       ((char *)startwrite + lencopy) -
-				       ((char *)outp + buf->vb.size));
-			lencopy = remain = (char *)outp + buf->vb.size -
+				       ((char *)outp + buf->length));
+			lencopy = remain = (char *)outp + buf->length -
 					   (char *)startwrite;
 		}
 		if (lencopy <= 0)
@@ -435,7 +421,11 @@ static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
 	}
 
 	/* Get the next buffer */
-	*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
+	*buf = list_entry(dma_q->active.next, struct au0828_buffer, list);
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
+	list_del(&(*buf)->list);
+	dma_q->pos = 0;
+	(*buf)->vb_buf = (*buf)->mem;
 	dev->isoc_ctl.buf = *buf;
 
 	return;
@@ -473,8 +463,8 @@ static void au0828_copy_vbi(struct au0828_dev *dev,
 
 	bytesperline = dev->vbi_width;
 
-	if (dma_q->pos + len > buf->vb.size)
-		len = buf->vb.size - dma_q->pos;
+	if (dma_q->pos + len > buf->length)
+		len = buf->length - dma_q->pos;
 
 	startread = p;
 	startwrite = outp + (dma_q->pos / 2);
@@ -497,7 +487,6 @@ static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
 				    struct au0828_buffer **buf)
 {
 	struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
-	char *outp;
 
 	if (list_empty(&dma_q->active)) {
 		au0828_isocdbg("No active queue to serve\n");
@@ -507,13 +496,12 @@ static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
 	}
 
 	/* Get the next buffer */
-	*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
+	*buf = list_entry(dma_q->active.next, struct au0828_buffer, list);
 	/* Cleans up buffer - Useful for testing for frame/URB loss */
-	outp = videobuf_to_vmalloc(&(*buf)->vb);
-	memset(outp, 0x00, (*buf)->vb.size);
-
+	list_del(&(*buf)->list);
+	dma_q->pos = 0;
+	(*buf)->vb_buf = (*buf)->mem;
 	dev->isoc_ctl.vbi_buf = *buf;
-
 	return;
 }
 
@@ -549,11 +537,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 
 	buf = dev->isoc_ctl.buf;
 	if (buf != NULL)
-		outp = videobuf_to_vmalloc(&buf->vb);
+		outp = vb2_plane_vaddr(&buf->vb, 0);
 
 	vbi_buf = dev->isoc_ctl.vbi_buf;
 	if (vbi_buf != NULL)
-		vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
+		vbioutp = vb2_plane_vaddr(&vbi_buf->vb, 0);
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 		int status = urb->iso_frame_desc[i].status;
@@ -593,8 +581,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 				if (vbi_buf == NULL)
 					vbioutp = NULL;
 				else
-					vbioutp = videobuf_to_vmalloc(
-						&vbi_buf->vb);
+					vbioutp = vb2_plane_vaddr(
+						&vbi_buf->vb, 0);
 
 				/* Video */
 				if (buf != NULL)
@@ -603,7 +591,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 				if (buf == NULL)
 					outp = NULL;
 				else
-					outp = videobuf_to_vmalloc(&buf->vb);
+					outp = vb2_plane_vaddr(&buf->vb, 0);
 
 				/* As long as isoc traffic is arriving, keep
 				   resetting the timer */
@@ -657,130 +645,59 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 	return rc;
 }
 
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-	     unsigned int *size)
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+		       unsigned int *nbuffers, unsigned int *nplanes,
+		       unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct au0828_fh *fh = vq->priv_data;
-	*size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
+	struct au0828_dev *dev = vb2_get_drv_priv(vq);
+	unsigned long img_size = dev->height * dev->bytesperline;
+	unsigned long size;
 
-	if (0 == *count)
-		*count = AU0828_DEF_BUF;
+	size = fmt ? fmt->fmt.pix.sizeimage : img_size;
+	if (size < img_size)
+		return -EINVAL;
 
-	if (*count < AU0828_MIN_BUF)
-		*count = AU0828_MIN_BUF;
-	return 0;
-}
+	*nplanes = 1;
+	sizes[0] = size;
 
-/* This is called *without* dev->slock held; please keep it that way */
-static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
-{
-	struct au0828_fh     *fh  = vq->priv_data;
-	struct au0828_dev    *dev = fh->dev;
-	unsigned long flags = 0;
-	if (in_interrupt())
-		BUG();
-
-	/* We used to wait for the buffer to finish here, but this didn't work
-	   because, as we were keeping the state as VIDEOBUF_QUEUED,
-	   videobuf_queue_cancel marked it as finished for us.
-	   (Also, it could wedge forever if the hardware was misconfigured.)
-
-	   This should be safe; by the time we get here, the buffer isn't
-	   queued anymore. If we ever start marking the buffers as
-	   VIDEOBUF_ACTIVE, it won't be, though.
-	*/
-	spin_lock_irqsave(&dev->slock, flags);
-	if (dev->isoc_ctl.buf == buf)
-		dev->isoc_ctl.buf = NULL;
-	spin_unlock_irqrestore(&dev->slock, flags);
-
-	videobuf_vmalloc_free(&buf->vb);
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+	return 0;
 }
 
 static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-						enum v4l2_field field)
+buffer_prepare(struct vb2_buffer *vb)
 {
-	struct au0828_fh     *fh  = vq->priv_data;
 	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
-	struct au0828_dev    *dev = fh->dev;
-	int                  rc = 0, urb_init = 0;
+	struct au0828_dev    *dev = vb2_get_drv_priv(vb->vb2_queue);
 
-	buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
+	buf->length = dev->height * dev->bytesperline;
 
-	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+	if (vb2_plane_size(vb, 0) < buf->length) {
+		pr_err("%s data will not fit into plane (%lu < %lu)\n",
+			__func__, vb2_plane_size(vb, 0), buf->length);
 		return -EINVAL;
-
-	buf->vb.width  = dev->width;
-	buf->vb.height = dev->height;
-	buf->vb.field  = field;
-
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		rc = videobuf_iolock(vq, &buf->vb, NULL);
-		if (rc < 0) {
-			pr_info("videobuf_iolock failed\n");
-			goto fail;
-		}
 	}
-
-	if (!dev->isoc_ctl.num_bufs)
-		urb_init = 1;
-
-	if (urb_init) {
-		rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
-				      AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
-				      au0828_isoc_copy);
-		if (rc < 0) {
-			pr_info("au0828_init_isoc failed\n");
-			goto fail;
-		}
-	}
-
-	buf->vb.state = VIDEOBUF_PREPARED;
+	vb2_set_plane_payload(&buf->vb, 0, buf->length);
 	return 0;
-
-fail:
-	free_buffer(vq, buf);
-	return rc;
 }
 
 static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+buffer_queue(struct vb2_buffer *vb)
 {
 	struct au0828_buffer    *buf     = container_of(vb,
 							struct au0828_buffer,
 							vb);
-	struct au0828_fh        *fh      = vq->priv_data;
-	struct au0828_dev       *dev     = fh->dev;
+	struct au0828_dev       *dev     = vb2_get_drv_priv(vb->vb2_queue);
 	struct au0828_dmaqueue  *vidq    = &dev->vidq;
+	unsigned long flags = 0;
 
-	buf->vb.state = VIDEOBUF_QUEUED;
-	list_add_tail(&buf->vb.queue, &vidq->active);
-}
-
-static void buffer_release(struct videobuf_queue *vq,
-				struct videobuf_buffer *vb)
-{
-	struct au0828_buffer   *buf  = container_of(vb,
-						    struct au0828_buffer,
-						    vb);
+	buf->mem = vb2_plane_vaddr(vb, 0);
+	buf->length = vb2_plane_size(vb, 0);
 
-	free_buffer(vq, buf);
+	spin_lock_irqsave(&dev->slock, flags);
+	list_add_tail(&buf->list, &vidq->active);
+	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-static struct videobuf_queue_ops au0828_video_qops = {
-	.buf_setup      = buffer_setup,
-	.buf_prepare    = buffer_prepare,
-	.buf_queue      = buffer_queue,
-	.buf_release    = buffer_release,
-};
-
-/* ------------------------------------------------------------------
-   V4L2 interface
-   ------------------------------------------------------------------*/
-
 static int au0828_i2s_init(struct au0828_dev *dev)
 {
 	/* Enable i2s mode */
@@ -829,7 +746,7 @@ static int au0828_analog_stream_enable(struct au0828_dev *d)
 	return 0;
 }
 
-int au0828_analog_stream_disable(struct au0828_dev *d)
+static int au0828_analog_stream_disable(struct au0828_dev *d)
 {
 	dprintk(1, "au0828_analog_stream_disable called\n");
 	au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
@@ -862,78 +779,133 @@ static int au0828_stream_interrupt(struct au0828_dev *dev)
 	return 0;
 }
 
-/*
- * au0828_release_resources
- * unregister v4l2 devices
- */
-void au0828_analog_unregister(struct au0828_dev *dev)
+int au0828_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
 {
-	dprintk(1, "au0828_release_resources called\n");
-	mutex_lock(&au0828_sysfs_lock);
+	struct au0828_dev *dev = vb2_get_drv_priv(vq);
+	int rc = 0;
 
-	if (dev->vdev)
-		video_unregister_device(dev->vdev);
-	if (dev->vbi_dev)
-		video_unregister_device(dev->vbi_dev);
+	dprintk(1, "au0828_start_analog_streaming called %d\n",
+		dev->streaming_users);
 
-	mutex_unlock(&au0828_sysfs_lock);
-}
+	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		dev->frame_count = 0;
+	else
+		dev->vbi_frame_count = 0;
+
+	if (dev->streaming_users == 0) {
+		/* If we were doing ac97 instead of i2s, it would go here...*/
+		au0828_i2s_init(dev);
+		rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
+				   AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
+				   au0828_isoc_copy);
+		if (rc < 0) {
+			pr_info("au0828_init_isoc failed\n");
+			return rc;
+		}
 
+		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			v4l2_device_call_all(&dev->v4l2_dev, 0, video,
+						s_stream, 1);
+			dev->vid_timeout_running = 1;
+			mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
+		} else if (vq->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+			dev->vbi_timeout_running = 1;
+			mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+		}
+	}
+	dev->streaming_users++;
+	return rc;
+}
 
-/* Usage lock check functions */
-static int res_get(struct au0828_fh *fh, unsigned int bit)
+static void au0828_stop_streaming(struct vb2_queue *vq)
 {
-	struct au0828_dev    *dev = fh->dev;
+	struct au0828_dev *dev = vb2_get_drv_priv(vq);
+	struct au0828_dmaqueue *vidq = &dev->vidq;
+	unsigned long flags = 0;
 
-	if (fh->resources & bit)
-		/* have it already allocated */
-		return 1;
+	dprintk(1, "au0828_stop_streaming called %d\n", dev->streaming_users);
 
-	/* is it free? */
-	if (dev->resources & bit) {
-		/* no, someone else uses it */
-		return 0;
+	if (dev->streaming_users-- == 1)
+		au0828_uninit_isoc(dev);
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+	dev->vid_timeout_running = 0;
+	del_timer_sync(&dev->vid_timeout);
+
+	spin_lock_irqsave(&dev->slock, flags);
+	if (dev->isoc_ctl.buf != NULL) {
+		vb2_buffer_done(&dev->isoc_ctl.buf->vb, VB2_BUF_STATE_ERROR);
+		dev->isoc_ctl.buf = NULL;
 	}
-	/* it's free, grab it */
-	fh->resources  |= bit;
-	dev->resources |= bit;
-	dprintk(1, "res: get %d\n", bit);
+	while (!list_empty(&vidq->active)) {
+		struct au0828_buffer *buf;
 
-	return 1;
+		buf = list_entry(vidq->active.next, struct au0828_buffer, list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		list_del(&buf->list);
+	}
+	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-static int res_check(struct au0828_fh *fh, unsigned int bit)
+void au0828_stop_vbi_streaming(struct vb2_queue *vq)
 {
-	return fh->resources & bit;
-}
+	struct au0828_dev *dev = vb2_get_drv_priv(vq);
+	struct au0828_dmaqueue *vbiq = &dev->vbiq;
+	unsigned long flags = 0;
 
-static int res_locked(struct au0828_dev *dev, unsigned int bit)
-{
-	return dev->resources & bit;
-}
+	dprintk(1, "au0828_stop_vbi_streaming called %d\n",
+		dev->streaming_users);
 
-static void res_free(struct au0828_fh *fh, unsigned int bits)
-{
-	struct au0828_dev    *dev = fh->dev;
+	if (dev->streaming_users-- == 1)
+		au0828_uninit_isoc(dev);
 
-	BUG_ON((fh->resources & bits) != bits);
+	spin_lock_irqsave(&dev->slock, flags);
+	if (dev->isoc_ctl.vbi_buf != NULL) {
+		vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb,
+				VB2_BUF_STATE_ERROR);
+		dev->isoc_ctl.vbi_buf = NULL;
+	}
+	while (!list_empty(&vbiq->active)) {
+		struct au0828_buffer *buf;
+
+		buf = list_entry(vbiq->active.next, struct au0828_buffer, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irqrestore(&dev->slock, flags);
 
-	fh->resources  &= ~bits;
-	dev->resources &= ~bits;
-	dprintk(1, "res: put %d\n", bits);
+	dev->vbi_timeout_running = 0;
+	del_timer_sync(&dev->vbi_timeout);
 }
 
-static int get_ressource(struct au0828_fh *fh)
+static struct vb2_ops au0828_video_qops = {
+	.queue_setup     = queue_setup,
+	.buf_prepare     = buffer_prepare,
+	.buf_queue       = buffer_queue,
+	.start_streaming = au0828_start_analog_streaming,
+	.stop_streaming  = au0828_stop_streaming,
+	.wait_prepare    = vb2_ops_wait_prepare,
+	.wait_finish     = vb2_ops_wait_finish,
+};
+
+/* ------------------------------------------------------------------
+   V4L2 interface
+   ------------------------------------------------------------------*/
+/*
+ * au0828_analog_unregister
+ * unregister v4l2 devices
+ */
+void au0828_analog_unregister(struct au0828_dev *dev)
 {
-	switch (fh->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		return AU0828_RESOURCE_VIDEO;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		return AU0828_RESOURCE_VBI;
-	default:
-		BUG();
-		return 0;
-	}
+	dprintk(1, "au0828_analog_unregister called\n");
+	mutex_lock(&au0828_sysfs_lock);
+
+	if (dev->vdev)
+		video_unregister_device(dev->vdev);
+	if (dev->vbi_dev)
+		video_unregister_device(dev->vbi_dev);
+
+	mutex_unlock(&au0828_sysfs_lock);
 }
 
 /* This function ensures that video frames continue to be delivered even if
@@ -951,8 +923,8 @@ static void au0828_vid_buffer_timeout(unsigned long data)
 
 	buf = dev->isoc_ctl.buf;
 	if (buf != NULL) {
-		vid_data = videobuf_to_vmalloc(&buf->vb);
-		memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
+		vid_data = vb2_plane_vaddr(&buf->vb, 0);
+		memset(vid_data, 0x00, buf->length); /* Blank green frame */
 		buffer_filled(dev, dma_q, buf);
 	}
 	get_next_buf(dma_q, &buf);
@@ -975,8 +947,8 @@ static void au0828_vbi_buffer_timeout(unsigned long data)
 
 	buf = dev->isoc_ctl.vbi_buf;
 	if (buf != NULL) {
-		vbi_data = videobuf_to_vmalloc(&buf->vb);
-		memset(vbi_data, 0x00, buf->vb.size);
+		vbi_data = vb2_plane_vaddr(&buf->vb, 0);
+		memset(vbi_data, 0x00, buf->length);
 		vbi_buffer_filled(dev, dma_q, buf);
 	}
 	vbi_get_next_buf(dma_q, &buf);
@@ -986,105 +958,65 @@ static void au0828_vbi_buffer_timeout(unsigned long data)
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-
 static int au0828_v4l2_open(struct file *filp)
 {
-	int ret = 0;
-	struct video_device *vdev = video_devdata(filp);
 	struct au0828_dev *dev = video_drvdata(filp);
-	struct au0828_fh *fh;
-	int type;
-
-	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER:
-		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		break;
-	case VFL_TYPE_VBI:
-		type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
-	if (NULL == fh) {
-		dprintk(1, "Failed allocate au0828_fh struct!\n");
-		return -ENOMEM;
-	}
+	int ret;
 
-	fh->type = type;
-	fh->dev = dev;
-	v4l2_fh_init(&fh->fh, vdev);
-	filp->private_data = fh;
+	dprintk(1,
+		"%s called std_set %d dev_state %d stream users %d users %d\n",
+		__func__, dev->std_set_in_tuner_core, dev->dev_state,
+		dev->streaming_users, dev->users);
 
-	if (mutex_lock_interruptible(&dev->lock)) {
-		kfree(fh);
+	if (mutex_lock_interruptible(&dev->lock))
 		return -ERESTARTSYS;
+
+	ret = v4l2_fh_open(filp);
+	if (ret) {
+		au0828_isocdbg("%s: v4l2_fh_open() returned error %d\n",
+				__func__, ret);
+		mutex_unlock(&dev->lock);
+		return ret;
 	}
+
 	if (dev->users == 0) {
 		au0828_analog_stream_enable(dev);
 		au0828_analog_stream_reset(dev);
-
-		/* If we were doing ac97 instead of i2s, it would go here...*/
-		au0828_i2s_init(dev);
-
 		dev->stream_state = STREAM_OFF;
 		dev->dev_state |= DEV_INITIALIZED;
 	}
-
 	dev->users++;
 	mutex_unlock(&dev->lock);
-
-	videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
-				    NULL, &dev->slock,
-				    V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				    V4L2_FIELD_INTERLACED,
-				    sizeof(struct au0828_buffer), fh,
-				    &dev->lock);
-
-	/* VBI Setup */
-	videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
-				    NULL, &dev->slock,
-				    V4L2_BUF_TYPE_VBI_CAPTURE,
-				    V4L2_FIELD_SEQ_TB,
-				    sizeof(struct au0828_buffer), fh,
-				    &dev->lock);
-	v4l2_fh_add(&fh->fh);
 	return ret;
 }
 
 static int au0828_v4l2_close(struct file *filp)
 {
 	int ret;
-	struct au0828_fh *fh = filp->private_data;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(filp);
+	struct video_device *vdev = video_devdata(filp);
+
+	dprintk(1,
+		"%s called std_set %d dev_state %d stream users %d users %d\n",
+		__func__, dev->std_set_in_tuner_core, dev->dev_state,
+		dev->streaming_users, dev->users);
 
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
 	mutex_lock(&dev->lock);
-	if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+	if (vdev->vfl_type == VFL_TYPE_GRABBER && dev->vid_timeout_running) {
 		/* Cancel timeout thread in case they didn't call streamoff */
 		dev->vid_timeout_running = 0;
 		del_timer_sync(&dev->vid_timeout);
-
-		videobuf_stop(&fh->vb_vidq);
-		res_free(fh, AU0828_RESOURCE_VIDEO);
-	}
-
-	if (res_check(fh, AU0828_RESOURCE_VBI)) {
+	} else if (vdev->vfl_type == VFL_TYPE_VBI &&
+			dev->vbi_timeout_running) {
 		/* Cancel timeout thread in case they didn't call streamoff */
 		dev->vbi_timeout_running = 0;
 		del_timer_sync(&dev->vbi_timeout);
-
-		videobuf_stop(&fh->vb_vbiq);
-		res_free(fh, AU0828_RESOURCE_VBI);
 	}
 
-	if (dev->users == 1 && video_is_registered(video_devdata(filp))) {
-		au0828_analog_stream_disable(dev);
-
-		au0828_uninit_isoc(dev);
+	if (dev->dev_state == DEV_DISCONNECTED)
+		goto end;
 
+	if (dev->users == 1) {
 		/* Save some power by putting tuner to sleep */
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
 		dev->std_set_in_tuner_core = 0;
@@ -1095,13 +1027,10 @@ static int au0828_v4l2_close(struct file *filp)
 		if (ret < 0)
 			pr_info("Au0828 can't set alternate to 0!\n");
 	}
-	mutex_unlock(&dev->lock);
-
-	videobuf_mmap_free(&fh->vb_vidq);
-	videobuf_mmap_free(&fh->vb_vbiq);
-	kfree(fh);
+end:
+	_vb2_fop_release(filp, NULL);
 	dev->users--;
-	wake_up_interruptible_nr(&dev->open, 1);
+	mutex_unlock(&dev->lock);
 	return 0;
 }
 
@@ -1113,6 +1042,9 @@ static void au0828_init_tuner(struct au0828_dev *dev)
 		.type = V4L2_TUNER_ANALOG_TV,
 	};
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	if (dev->std_set_in_tuner_core)
 		return;
 	dev->std_set_in_tuner_core = 1;
@@ -1125,98 +1057,6 @@ static void au0828_init_tuner(struct au0828_dev *dev)
 	i2c_gate_ctrl(dev, 0);
 }
 
-static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
-				size_t count, loff_t *pos)
-{
-	struct au0828_fh *fh = filp->private_data;
-	struct au0828_dev *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (mutex_lock_interruptible(&dev->lock))
-		return -ERESTARTSYS;
-	au0828_init_tuner(dev);
-	mutex_unlock(&dev->lock);
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		if (res_locked(dev, AU0828_RESOURCE_VIDEO))
-			return -EBUSY;
-
-		return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
-					filp->f_flags & O_NONBLOCK);
-	}
-
-	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		if (!res_get(fh, AU0828_RESOURCE_VBI))
-			return -EBUSY;
-
-		if (dev->vbi_timeout_running == 0) {
-			/* Handle case where caller tries to read without
-			   calling streamon first */
-			dev->vbi_timeout_running = 1;
-			mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
-		}
-
-		return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
-					    filp->f_flags & O_NONBLOCK);
-	}
-
-	return 0;
-}
-
-static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
-{
-	struct au0828_fh *fh = filp->private_data;
-	struct au0828_dev *dev = fh->dev;
-	unsigned long req_events = poll_requested_events(wait);
-	unsigned int res;
-
-	if (check_dev(dev) < 0)
-		return POLLERR;
-
-	res = v4l2_ctrl_poll(filp, wait);
-	if (!(req_events & (POLLIN | POLLRDNORM)))
-		return res;
-
-	if (mutex_lock_interruptible(&dev->lock))
-		return -ERESTARTSYS;
-	au0828_init_tuner(dev);
-	mutex_unlock(&dev->lock);
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		if (!res_get(fh, AU0828_RESOURCE_VIDEO))
-			return POLLERR;
-		return res | videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-	}
-	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		if (!res_get(fh, AU0828_RESOURCE_VBI))
-			return POLLERR;
-		return res | videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
-	}
-	return POLLERR;
-}
-
-static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct au0828_fh *fh    = filp->private_data;
-	struct au0828_dev *dev   = fh->dev;
-	int		 rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-		rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
-
-	return rc;
-}
-
 static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
 			     struct v4l2_format *format)
 {
@@ -1268,13 +1108,14 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
 	return 0;
 }
 
-
 static int vidioc_querycap(struct file *file, void  *priv,
 			   struct v4l2_capability *cap)
 {
 	struct video_device *vdev = video_devdata(file);
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	strlcpy(cap->driver, "au0828", sizeof(cap->driver));
 	strlcpy(cap->card, dev->board.name, sizeof(cap->card));
@@ -1300,6 +1141,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 	if (f->index)
 		return -EINVAL;
 
+	dprintk(1, "%s called\n", __func__);
+
 	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	strcpy(f->description, "Packed YUV2");
 
@@ -1312,8 +1155,10 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct au0828_fh *fh  = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	f->fmt.pix.width = dev->width;
 	f->fmt.pix.height = dev->height;
@@ -1329,8 +1174,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
-	struct au0828_fh *fh  = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
 }
@@ -1338,15 +1185,17 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct au0828_fh *fh  = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 	int rc;
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	rc = check_dev(dev);
 	if (rc < 0)
 		return rc;
 
-	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+	if (vb2_is_busy(&dev->vb_vidq)) {
 		pr_info("%s queue busy\n", __func__);
 		rc = -EBUSY;
 		goto out;
@@ -1359,8 +1208,16 @@ out:
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
+	if (norm == dev->std)
+		return 0;
+
+	if (dev->streaming_users > 0)
+		return -EBUSY;
 
 	dev->std = norm;
 
@@ -1383,8 +1240,10 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	*norm = dev->std;
 	return 0;
@@ -1393,8 +1252,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 static int vidioc_enum_input(struct file *file, void *priv,
 				struct v4l2_input *input)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 	unsigned int tmp;
 
 	static const char *inames[] = {
@@ -1407,6 +1265,9 @@ static int vidioc_enum_input(struct file *file, void *priv,
 		[AU0828_VMUX_DEBUG] = "tv debug"
 	};
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	tmp = input->index;
 
 	if (tmp >= AU0828_MAX_INPUT)
@@ -1432,8 +1293,11 @@ static int vidioc_enum_input(struct file *file, void *priv,
 
 static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	*i = dev->ctrl_input;
 	return 0;
 }
@@ -1442,6 +1306,9 @@ static void au0828_s_input(struct au0828_dev *dev, int index)
 {
 	int i;
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	switch (AUVI_INPUT(index).type) {
 	case AU0828_VMUX_SVIDEO:
 		dev->input_type = AU0828_VMUX_SVIDEO;
@@ -1491,8 +1358,7 @@ static void au0828_s_input(struct au0828_dev *dev, int index)
 
 static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 
 	dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
 		index);
@@ -1510,6 +1376,8 @@ static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a)
 	if (a->index > 1)
 		return -EINVAL;
 
+	dprintk(1, "%s called\n", __func__);
+
 	if (a->index == 0)
 		strcpy(a->name, "Television");
 	else
@@ -1521,8 +1389,10 @@ static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a)
 
 static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	a->index = dev->ctrl_ainput;
 	if (a->index == 0)
@@ -1536,22 +1406,26 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 
 static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 
 	if (a->index != dev->ctrl_ainput)
 		return -EINVAL;
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 
 	if (t->index != 0)
 		return -EINVAL;
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	strcpy(t->name, "Auvitek tuner");
 
 	au0828_init_tuner(dev);
@@ -1564,12 +1438,14 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 static int vidioc_s_tuner(struct file *file, void *priv,
 				const struct v4l2_tuner *t)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 
 	if (t->index != 0)
 		return -EINVAL;
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	au0828_init_tuner(dev);
 	i2c_gate_ctrl(dev, 1);
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
@@ -1585,11 +1461,12 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *freq)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 
 	if (freq->tuner != 0)
 		return -EINVAL;
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 	freq->frequency = dev->ctrl_freq;
 	return 0;
 }
@@ -1597,13 +1474,15 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
 				const struct v4l2_frequency *freq)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 	struct v4l2_frequency new_freq = *freq;
 
 	if (freq->tuner != 0)
 		return -EINVAL;
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	au0828_init_tuner(dev);
 	i2c_gate_ctrl(dev, 1);
 
@@ -1625,8 +1504,10 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 				struct v4l2_format *format)
 {
-	struct au0828_fh      *fh  = priv;
-	struct au0828_dev     *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	format->fmt.vbi.samples_per_line = dev->vbi_width;
 	format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -1646,12 +1527,14 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 static int vidioc_cropcap(struct file *file, void *priv,
 			  struct v4l2_cropcap *cc)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
 
 	if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
+
 	cc->bounds.left = 0;
 	cc->bounds.top = 0;
 	cc->bounds.width = dev->width;
@@ -1665,105 +1548,14 @@ static int vidioc_cropcap(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_streamon(struct file *file, void *priv,
-			   enum v4l2_buf_type type)
-{
-	struct au0828_fh      *fh  = priv;
-	struct au0828_dev     *dev = fh->dev;
-	int                   rc = -EINVAL;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (unlikely(type != fh->type))
-		return -EINVAL;
-
-	dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
-		fh, type, fh->resources, dev->resources);
-
-	if (unlikely(!res_get(fh, get_ressource(fh))))
-		return -EBUSY;
-
-	au0828_init_tuner(dev);
-	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		au0828_analog_stream_enable(dev);
-		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
-	}
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		rc = videobuf_streamon(&fh->vb_vidq);
-		dev->vid_timeout_running = 1;
-		mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
-	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		rc = videobuf_streamon(&fh->vb_vbiq);
-		dev->vbi_timeout_running = 1;
-		mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
-	}
-
-	return rc;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-			    enum v4l2_buf_type type)
-{
-	struct au0828_fh      *fh  = priv;
-	struct au0828_dev     *dev = fh->dev;
-	int                   rc;
-	int                   i;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-	    fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
-		return -EINVAL;
-	if (type != fh->type)
-		return -EINVAL;
-
-	dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
-		fh, type, fh->resources, dev->resources);
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		dev->vid_timeout_running = 0;
-		del_timer_sync(&dev->vid_timeout);
-
-		au0828_analog_stream_disable(dev);
-		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
-		rc = au0828_stream_interrupt(dev);
-		if (rc != 0)
-			return rc;
-
-		for (i = 0; i < AU0828_MAX_INPUT; i++) {
-			if (AUVI_INPUT(i).audio_setup == NULL)
-				continue;
-			(AUVI_INPUT(i).audio_setup)(dev, 0);
-		}
-
-		if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
-			videobuf_streamoff(&fh->vb_vidq);
-			res_free(fh, AU0828_RESOURCE_VIDEO);
-		}
-	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		dev->vbi_timeout_running = 0;
-		del_timer_sync(&dev->vbi_timeout);
-
-		if (res_check(fh, AU0828_RESOURCE_VBI)) {
-			videobuf_streamoff(&fh->vb_vbiq);
-			res_free(fh, AU0828_RESOURCE_VBI);
-		}
-	}
-
-	return 0;
-}
-
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register(struct file *file, void *priv,
 			     struct v4l2_dbg_register *reg)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	reg->val = au0828_read(dev, reg->reg);
 	reg->size = 1;
@@ -1773,8 +1565,10 @@ static int vidioc_g_register(struct file *file, void *priv,
 static int vidioc_s_register(struct file *file, void *priv,
 			     const struct v4l2_dbg_register *reg)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	struct au0828_dev *dev = video_drvdata(file);
+
+	dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
+		dev->std_set_in_tuner_core, dev->dev_state);
 
 	return au0828_writereg(dev, reg->reg, reg->val);
 }
@@ -1784,93 +1578,13 @@ static int vidioc_log_status(struct file *file, void *fh)
 {
 	struct video_device *vdev = video_devdata(file);
 
+	dprintk(1, "%s called\n", __func__);
+
 	v4l2_ctrl_log_status(file, fh);
 	v4l2_device_call_all(vdev->v4l2_dev, 0, core, log_status);
 	return 0;
 }
 
-static int vidioc_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *rb)
-{
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		rc = videobuf_reqbufs(&fh->vb_vidq, rb);
-	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-		rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
-
-	return rc;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-			   struct v4l2_buffer *b)
-{
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		rc = videobuf_querybuf(&fh->vb_vidq, b);
-	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-		rc = videobuf_querybuf(&fh->vb_vbiq, b);
-
-	return rc;
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		rc = videobuf_qbuf(&fh->vb_vidq, b);
-	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-		rc = videobuf_qbuf(&fh->vb_vbiq, b);
-
-	return rc;
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	/* Workaround for a bug in the au0828 hardware design that sometimes
-	   results in the colorspace being inverted */
-	if (dev->greenscreen_detected == 1) {
-		dprintk(1, "Detected green frame.  Resetting stream...\n");
-		au0828_analog_stream_reset(dev);
-		dev->greenscreen_detected = 0;
-	}
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
-	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-		rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
-
-	return rc;
-}
-
 void au0828_v4l2_suspend(struct au0828_dev *dev)
 {
 	struct urb *urb;
@@ -1938,9 +1652,9 @@ static struct v4l2_file_operations au0828_v4l_fops = {
 	.owner      = THIS_MODULE,
 	.open       = au0828_v4l2_open,
 	.release    = au0828_v4l2_close,
-	.read       = au0828_v4l2_read,
-	.poll       = au0828_v4l2_poll,
-	.mmap       = au0828_v4l2_mmap,
+	.read       = vb2_fop_read,
+	.poll       = vb2_fop_poll,
+	.mmap       = vb2_fop_mmap,
 	.unlocked_ioctl = video_ioctl2,
 };
 
@@ -1957,17 +1671,24 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_g_audio             = vidioc_g_audio,
 	.vidioc_s_audio             = vidioc_s_audio,
 	.vidioc_cropcap             = vidioc_cropcap,
-	.vidioc_reqbufs             = vidioc_reqbufs,
-	.vidioc_querybuf            = vidioc_querybuf,
-	.vidioc_qbuf                = vidioc_qbuf,
-	.vidioc_dqbuf               = vidioc_dqbuf,
+
+	.vidioc_reqbufs             = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs         = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf         = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf            = vb2_ioctl_querybuf,
+	.vidioc_qbuf                = vb2_ioctl_qbuf,
+	.vidioc_dqbuf               = vb2_ioctl_dqbuf,
+	.vidioc_expbuf               = vb2_ioctl_expbuf,
+
 	.vidioc_s_std               = vidioc_s_std,
 	.vidioc_g_std               = vidioc_g_std,
 	.vidioc_enum_input          = vidioc_enum_input,
 	.vidioc_g_input             = vidioc_g_input,
 	.vidioc_s_input             = vidioc_s_input,
-	.vidioc_streamon            = vidioc_streamon,
-	.vidioc_streamoff           = vidioc_streamoff,
+
+	.vidioc_streamon            = vb2_ioctl_streamon,
+	.vidioc_streamoff           = vb2_ioctl_streamoff,
+
 	.vidioc_g_tuner             = vidioc_g_tuner,
 	.vidioc_s_tuner             = vidioc_s_tuner,
 	.vidioc_g_frequency         = vidioc_g_frequency,
@@ -1988,6 +1709,42 @@ static const struct video_device au0828_video_template = {
 	.tvnorms                    = V4L2_STD_NTSC_M | V4L2_STD_PAL_M,
 };
 
+static int au0828_vb2_setup(struct au0828_dev *dev)
+{
+	int rc;
+	struct vb2_queue *q;
+
+	/* Setup Videobuf2 for Video capture */
+	q = &dev->vb_vidq;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->drv_priv = dev;
+	q->buf_struct_size = sizeof(struct au0828_buffer);
+	q->ops = &au0828_video_qops;
+	q->mem_ops = &vb2_vmalloc_memops;
+
+	rc = vb2_queue_init(q);
+	if (rc < 0)
+		return rc;
+
+	/* Setup Videobuf2 for VBI capture */
+	q = &dev->vb_vbiq;
+	q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->drv_priv = dev;
+	q->buf_struct_size = sizeof(struct au0828_buffer);
+	q->ops = &au0828_vbi_qops;
+	q->mem_ops = &vb2_vmalloc_memops;
+
+	rc = vb2_queue_init(q);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
 /**************************************************************************/
 
 int au0828_analog_register(struct au0828_dev *dev,
@@ -2030,7 +1787,6 @@ int au0828_analog_register(struct au0828_dev *dev,
 	}
 	if (!(dev->isoc_in_endpointaddr)) {
 		pr_info("Could not locate isoc endpoint\n");
-		kfree(dev);
 		return -ENODEV;
 	}
 
@@ -2039,17 +1795,12 @@ int au0828_analog_register(struct au0828_dev *dev,
 
 	/* init video dma queues */
 	INIT_LIST_HEAD(&dev->vidq.active);
-	INIT_LIST_HEAD(&dev->vidq.queued);
 	INIT_LIST_HEAD(&dev->vbiq.active);
-	INIT_LIST_HEAD(&dev->vbiq.queued);
-
-	dev->vid_timeout.function = au0828_vid_buffer_timeout;
-	dev->vid_timeout.data = (unsigned long) dev;
-	init_timer(&dev->vid_timeout);
 
-	dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
-	dev->vbi_timeout.data = (unsigned long) dev;
-	init_timer(&dev->vbi_timeout);
+	setup_timer(&dev->vid_timeout, au0828_vid_buffer_timeout,
+		    (unsigned long)dev);
+	setup_timer(&dev->vbi_timeout, au0828_vbi_buffer_timeout,
+		    (unsigned long)dev);
 
 	dev->width = NTSC_STD_W;
 	dev->height = NTSC_STD_H;
@@ -2078,18 +1829,34 @@ int au0828_analog_register(struct au0828_dev *dev,
 		goto err_vdev;
 	}
 
+	mutex_init(&dev->vb_queue_lock);
+	mutex_init(&dev->vb_vbi_queue_lock);
+
 	/* Fill the video capture device struct */
 	*dev->vdev = au0828_video_template;
 	dev->vdev->v4l2_dev = &dev->v4l2_dev;
 	dev->vdev->lock = &dev->lock;
+	dev->vdev->queue = &dev->vb_vidq;
+	dev->vdev->queue->lock = &dev->vb_queue_lock;
 	strcpy(dev->vdev->name, "au0828a video");
 
 	/* Setup the VBI device */
 	*dev->vbi_dev = au0828_video_template;
 	dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
 	dev->vbi_dev->lock = &dev->lock;
+	dev->vbi_dev->queue = &dev->vb_vbiq;
+	dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
 	strcpy(dev->vbi_dev->name, "au0828a vbi");
 
+	/* initialize videobuf2 stuff */
+	retval = au0828_vb2_setup(dev);
+	if (retval != 0) {
+		dprintk(1, "unable to setup videobuf2 queues (error = %d).\n",
+			retval);
+		ret = -ENODEV;
+		goto err_vbi_dev;
+	}
+
 	/* Register the v4l2 device */
 	video_set_drvdata(dev->vdev, dev);
 	retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
@@ -2097,7 +1864,7 @@ int au0828_analog_register(struct au0828_dev *dev,
 		dprintk(1, "unable to register video device (error = %d).\n",
 			retval);
 		ret = -ENODEV;
-		goto err_vbi_dev;
+		goto err_reg_vdev;
 	}
 
 	/* Register the vbi device */
@@ -2107,13 +1874,18 @@ int au0828_analog_register(struct au0828_dev *dev,
 		dprintk(1, "unable to register vbi device (error = %d).\n",
 			retval);
 		ret = -ENODEV;
-		goto err_vbi_dev;
+		goto err_reg_vbi_dev;
 	}
 
 	dprintk(1, "%s completed!\n", __func__);
 
 	return 0;
 
+err_reg_vbi_dev:
+	video_unregister_device(dev->vdev);
+err_reg_vdev:
+	vb2_queue_release(&dev->vb_vidq);
+	vb2_queue_release(&dev->vb_vbiq);
 err_vbi_dev:
 	video_device_release(dev->vbi_dev);
 err_vdev:
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 36815a369c68..eb1518742ae6 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -28,7 +28,7 @@
 
 /* Analog */
 #include <linux/videodev2.h>
-#include <media/videobuf-vmalloc.h>
+#include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
@@ -126,17 +126,7 @@ enum au0828_dev_state {
 	DEV_MISCONFIGURED = 0x04
 };
 
-struct au0828_fh {
-	/* must be the first field of this struct! */
-	struct v4l2_fh fh;
-
-	struct au0828_dev *dev;
-	unsigned int  resources;
-
-	struct videobuf_queue        vb_vidq;
-	struct videobuf_queue        vb_vbiq;
-	enum v4l2_buf_type           type;
-};
+struct au0828_dev;
 
 struct au0828_usb_isoc_ctl {
 		/* max packet size of isoc transaction */
@@ -177,21 +167,20 @@ struct au0828_usb_isoc_ctl {
 /* buffer for one video frame */
 struct au0828_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer vb;
+	struct vb2_buffer vb;
+	struct list_head list;
 
-	struct list_head frame;
+	void *mem;
+	unsigned long length;
 	int top_field;
-	int receiving;
+	/* pointer to vmalloc memory address in vb */
+	char *vb_buf;
 };
 
 struct au0828_dmaqueue {
 	struct list_head       active;
-	struct list_head       queued;
-
-	wait_queue_head_t          wq;
-
 	/* Counters to control buffer fill */
-	int                        pos;
+	int                    pos;
 };
 
 struct au0828_dev {
@@ -220,14 +209,26 @@ struct au0828_dev {
 	struct au0828_rc *ir;
 #endif
 
-	int users;
-	unsigned int resources;	/* resources in use */
 	struct video_device *vdev;
 	struct video_device *vbi_dev;
+
+	/* Videobuf2 */
+	struct vb2_queue vb_vidq;
+	struct vb2_queue vb_vbiq;
+	struct mutex vb_queue_lock;
+	struct mutex vb_vbi_queue_lock;
+
+	unsigned int frame_count;
+	unsigned int vbi_frame_count;
+
 	struct timer_list vid_timeout;
 	int vid_timeout_running;
 	struct timer_list vbi_timeout;
 	int vbi_timeout_running;
+
+	int users;
+	int streaming_users;
+
 	int width;
 	int height;
 	int vbi_width;
@@ -242,7 +243,6 @@ struct au0828_dev {
 	__u8 isoc_in_endpointaddr;
 	u8 isoc_init_ok;
 	int greenscreen_detected;
-	unsigned int frame_count;
 	int ctrl_freq;
 	int input_type;
 	int std_set_in_tuner_core;
@@ -277,6 +277,7 @@ struct au0828_dev {
 	char *dig_transfer_buffer[URB_COUNT];
 };
 
+
 /* ----------------------------------------------------------- */
 #define au0828_read(dev, reg) au0828_readreg(dev, reg)
 #define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
@@ -309,13 +310,15 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* au0828-video.c */
-int au0828_analog_register(struct au0828_dev *dev,
+extern int au0828_analog_register(struct au0828_dev *dev,
 			   struct usb_interface *interface);
-int au0828_analog_stream_disable(struct au0828_dev *d);
-void au0828_analog_unregister(struct au0828_dev *dev);
+extern void au0828_analog_unregister(struct au0828_dev *dev);
+extern int au0828_start_analog_streaming(struct vb2_queue *vq,
+						unsigned int count);
+extern void au0828_stop_vbi_streaming(struct vb2_queue *vq);
 #ifdef CONFIG_VIDEO_AU0828_V4L2
-void au0828_v4l2_suspend(struct au0828_dev *dev);
-void au0828_v4l2_resume(struct au0828_dev *dev);
+extern void au0828_v4l2_suspend(struct au0828_dev *dev);
+extern void au0828_v4l2_resume(struct au0828_dev *dev);
 #else
 static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { };
 static inline void au0828_v4l2_resume(struct au0828_dev *dev) { };
@@ -329,7 +332,7 @@ void au0828_dvb_suspend(struct au0828_dev *dev);
 void au0828_dvb_resume(struct au0828_dev *dev);
 
 /* au0828-vbi.c */
-extern struct videobuf_queue_ops au0828_vbi_qops;
+extern struct vb2_ops au0828_vbi_qops;
 
 #define dprintk(level, fmt, arg...)\
 	do { if (au0828_debug & level)\
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index ae05d591f228..da03733690bd 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -1403,7 +1403,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 	struct usb_interface_assoc_descriptor *assoc_desc;
 
 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
-	udev = usb_get_dev(interface_to_usbdev(interface));
 
 	/*
 	 * Interface number 0 - IR interface (handled by mceusb driver)
@@ -1424,11 +1423,13 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 		}
 	} while (test_and_set_bit(nr, &cx231xx_devused));
 
+	udev = usb_get_dev(interface_to_usbdev(interface));
+
 	/* allocate memory for our device state and initialize it */
 	dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
-		clear_bit(nr, &cx231xx_devused);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_if;
 	}
 
 	snprintf(dev->name, 29, "cx231xx #%d", nr);
@@ -1582,7 +1583,7 @@ err_v4l2:
 	usb_set_intfdata(interface, NULL);
 err_if:
 	usb_put_dev(udev);
-	clear_bit(dev->devno, &cx231xx_devused);
+	clear_bit(nr, &cx231xx_devused);
 	return retval;
 }
 
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index 53ca12c1ff69..ecea76fe07f6 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -2062,7 +2062,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
 	*vfd = *template;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->release = video_device_release;
-	vfd->debug = video_debug;
 	vfd->lock = &dev->lock;
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index f9e262eb0db9..6d6f3ee812f6 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -532,15 +532,7 @@ struct cx231xx_video_mode {
 	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
 	u16 end_point_addr;
 };
-/*
-struct cx23885_dmaqueue {
-	struct list_head       active;
-	struct list_head       queued;
-	struct timer_list      timeout;
-	struct btcx_riscmem    stopper;
-	u32                    count;
-};
-*/
+
 struct cx231xx_tsport {
 	struct cx231xx *dev;
 
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 14e111e13e54..41c6363dff08 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -354,6 +354,7 @@ struct dvb_usb_adapter {
  * @name: device name
  * @rc_map: name of rc codes table
  * @rc_polling_active: set when RC polling is active
+ * @intf: pointer to the device's struct usb_interface
  * @udev: pointer to the device's struct usb_device
  * @rc: remote controller configuration
  * @powered: indicated whether the device is power or not
@@ -370,6 +371,7 @@ struct dvb_usb_device {
 	const char *name;
 	const char *rc_map;
 	bool rc_polling_active;
+	struct usb_interface *intf;
 	struct usb_device *udev;
 	struct dvb_usb_rc rc;
 	int powered;
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 1950f37df835..9913e0f59485 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -868,6 +868,7 @@ int dvb_usbv2_probe(struct usb_interface *intf,
 		goto err;
 	}
 
+	d->intf = intf;
 	d->name = driver_info->name;
 	d->rc_map = driver_info->rc_map;
 	d->udev = udev;
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 994de53a574b..5de6f7c04d09 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -126,9 +126,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 struct lme2510_state {
 	unsigned long int_urb_due;
+	fe_status_t lock_status;
 	u8 id;
 	u8 tuner_config;
-	u8 signal_lock;
 	u8 signal_level;
 	u8 signal_sn;
 	u8 time_key;
@@ -143,6 +143,12 @@ struct lme2510_state {
 	void *buffer;
 	struct urb *lme_urb;
 	void *usb_buffer;
+	/* Frontend original calls */
+	int (*fe_read_status)(struct dvb_frontend *, fe_status_t *);
+	int (*fe_read_signal_strength)(struct dvb_frontend *, u16 *);
+	int (*fe_read_snr)(struct dvb_frontend *, u16 *);
+	int (*fe_read_ber)(struct dvb_frontend *, u32 *);
+	int (*fe_read_ucblocks)(struct dvb_frontend *, u32 *);
 	int (*fe_set_voltage)(struct dvb_frontend *, fe_sec_voltage_t);
 	u8 dvb_usb_lme2510_firmware;
 };
@@ -258,6 +264,7 @@ static void lme2510_int_response(struct urb *lme_urb)
 	static u8 *ibuf, *rbuf;
 	int i = 0, offset;
 	u32 key;
+	u8 signal_lock = 0;
 
 	switch (lme_urb->status) {
 	case 0:
@@ -298,8 +305,7 @@ static void lme2510_int_response(struct urb *lme_urb)
 		case 0xbb:
 			switch (st->tuner_config) {
 			case TUNER_LG:
-				if (ibuf[2] > 0)
-					st->signal_lock = ibuf[2];
+				signal_lock = ibuf[2] & BIT(5);
 				st->signal_level = ibuf[4];
 				st->signal_sn = ibuf[3];
 				st->time_key = ibuf[7];
@@ -308,29 +314,29 @@ static void lme2510_int_response(struct urb *lme_urb)
 			case TUNER_S0194:
 				/* Tweak for earlier firmware*/
 				if (ibuf[1] == 0x03) {
-					if (ibuf[2] > 1)
-						st->signal_lock = ibuf[2];
+					signal_lock = ibuf[2] & BIT(4);
 					st->signal_level = ibuf[3];
 					st->signal_sn = ibuf[4];
 				} else {
 					st->signal_level = ibuf[4];
 					st->signal_sn = ibuf[5];
-					st->signal_lock =
-						(st->signal_lock & 0xf7) +
-						((ibuf[2] & 0x01) << 0x03);
 				}
 				break;
 			case TUNER_RS2000:
-				if (ibuf[2] & 0x1)
-					st->signal_lock = 0xff;
-				else
-					st->signal_lock = 0x00;
+				signal_lock = ibuf[2] & 0xee;
 				st->signal_level = ibuf[5];
 				st->signal_sn = ibuf[4];
 				st->time_key = ibuf[7];
 			default:
 				break;
 			}
+
+			/* Interrupt will also throw just BIT 0 as lock */
+			signal_lock |= ibuf[2] & BIT(0);
+
+			if (!signal_lock)
+				st->lock_status &= ~FE_HAS_LOCK;
+
 			debug_data_snipet(5, "INT Remote data snipet in", ibuf);
 		break;
 		case 0xcc:
@@ -344,15 +350,17 @@ static void lme2510_int_response(struct urb *lme_urb)
 
 	usb_submit_urb(lme_urb, GFP_ATOMIC);
 
-	/* interrupt urb is due every 48 msecs while streaming
-	 *	add 12msecs for system lag */
-	st->int_urb_due = jiffies + msecs_to_jiffies(60);
+	/* Interrupt urb is due every 48 msecs while streaming the buffer
+	 * stores up to 4 periods if missed. Allow 200 msec for next interrupt.
+	 */
+	st->int_urb_due = jiffies + msecs_to_jiffies(200);
 }
 
 static int lme2510_int_read(struct dvb_usb_adapter *adap)
 {
 	struct dvb_usb_device *d = adap_to_d(adap);
 	struct lme2510_state *lme_int = adap_to_priv(adap);
+	struct usb_host_endpoint *ep;
 
 	lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC);
 
@@ -374,6 +382,12 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
 				adap,
 				8);
 
+	/* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */
+	ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe);
+
+	if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
+		lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa),
+
 	lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC);
@@ -449,170 +463,13 @@ static int lme2510_return_status(struct dvb_usb_device *d)
 static int lme2510_msg(struct dvb_usb_device *d,
 		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
 {
-	int ret = 0;
 	struct lme2510_state *st = d->priv;
 
-	if (st->i2c_talk_onoff == 1) {
-
-		ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-
-		switch (st->tuner_config) {
-		case TUNER_LG:
-			if (wbuf[2] == 0x1c) {
-				if (wbuf[3] == 0x0e) {
-					st->signal_lock = rbuf[1];
-					if ((st->stream_on & 1) &&
-						(st->signal_lock & 0x10)) {
-						lme2510_stream_restart(d);
-						st->i2c_talk_onoff = 0;
-					}
-					msleep(80);
-				}
-			}
-			break;
-		case TUNER_S7395:
-			if (wbuf[2] == 0xd0) {
-				if (wbuf[3] == 0x24) {
-					st->signal_lock = rbuf[1];
-					if ((st->stream_on & 1) &&
-						(st->signal_lock & 0x8)) {
-						lme2510_stream_restart(d);
-						st->i2c_talk_onoff = 0;
-					}
-				}
-			}
-			break;
-		case TUNER_S0194:
-			if (wbuf[2] == 0xd0) {
-				if (wbuf[3] == 0x1b) {
-					st->signal_lock = rbuf[1];
-					if ((st->stream_on & 1) &&
-						(st->signal_lock & 0x8)) {
-						lme2510_stream_restart(d);
-						st->i2c_talk_onoff = 0;
-					}
-				}
-			}
-			break;
-		case TUNER_RS2000:
-		default:
-			break;
-		}
-	} else {
-		/* TODO rewrite this section */
-		switch (st->tuner_config) {
-		case TUNER_LG:
-			switch (wbuf[3]) {
-			case 0x0e:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-				break;
-			case 0x43:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_level;
-				break;
-			case 0x1c:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_sn;
-				break;
-			case 0x15:
-			case 0x16:
-			case 0x17:
-			case 0x18:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0x00;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-			break;
-		case TUNER_S7395:
-			switch (wbuf[3]) {
-			case 0x10:
-				rbuf[0] = 0x55;
-				rbuf[1] = (st->signal_level & 0x80)
-						? 0 : (st->signal_level * 2);
-				break;
-			case 0x2d:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_sn;
-				break;
-			case 0x24:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-				break;
-			case 0x2e:
-			case 0x26:
-			case 0x27:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0x00;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-			break;
-		case TUNER_S0194:
-			switch (wbuf[3]) {
-			case 0x18:
-				rbuf[0] = 0x55;
-				rbuf[1] = (st->signal_level & 0x80)
-						? 0 : (st->signal_level * 2);
-				break;
-			case 0x24:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_sn;
-				break;
-			case 0x1b:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-				break;
-			case 0x19:
-			case 0x25:
-			case 0x1e:
-			case 0x1d:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0x00;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-			break;
-		case TUNER_RS2000:
-			switch (wbuf[3]) {
-			case 0x8c:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-
-				/* If int_urb_due overdue
-				 *  set rbuf[1] to 0 to clear lock */
-				if (time_after(jiffies,	st->int_urb_due))
-					rbuf[1] = 0;
-
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-		default:
-			break;
-		}
-
-		deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)",
-				wbuf[3], rbuf[1]);
-
-	}
+	st->i2c_talk_onoff = 1;
 
-	return ret;
+	return lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
 }
 
-
 static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 				 int num)
 {
@@ -935,26 +792,8 @@ static struct stv0299_config sharp_z0194_config = {
 	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
 };
 
-static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe,
-	int caller)
-{
-	struct dvb_usb_adapter *adap = fe_to_adap(fe);
-	struct dvb_usb_device *d = adap_to_d(adap);
-	struct lme2510_state *st = d->priv;
-
-	mutex_lock(&d->i2c_mutex);
-	if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) {
-		st->i2c_talk_onoff = 0;
-		lme2510_stream_restart(d);
-	}
-	mutex_unlock(&d->i2c_mutex);
-
-	return 0;
-}
-
 static struct m88rs2000_config m88rs2000_config = {
-	.demod_addr = 0x68,
-	.set_ts_params = dm04_rs2000_set_ts_param,
+	.demod_addr = 0x68
 };
 
 static struct ts2020_config ts2020_config = {
@@ -998,27 +837,101 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
 	return (ret < 0) ? -ENODEV : 0;
 }
 
-static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe,
-	u16 *strength)
+static int dm04_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct dvb_usb_device *d = fe_to_d(fe);
+	struct lme2510_state *st = d->priv;
+	int ret = 0;
+
+	if (st->i2c_talk_onoff) {
+		if (st->fe_read_status) {
+			ret = st->fe_read_status(fe, status);
+			if (ret < 0)
+				return ret;
+		}
+
+		st->lock_status = *status;
+
+		if (*status & FE_HAS_LOCK && st->stream_on) {
+			mutex_lock(&d->i2c_mutex);
+
+			st->i2c_talk_onoff = 0;
+			ret = lme2510_stream_restart(d);
+
+			mutex_unlock(&d->i2c_mutex);
+		}
+
+		return ret;
+	}
+
+	/* Timeout of interrupt reached on RS2000 */
+	if (st->tuner_config == TUNER_RS2000 &&
+	    time_after(jiffies, st->int_urb_due))
+		st->lock_status &= ~FE_HAS_LOCK;
+
+	*status = st->lock_status;
+
+	if (!(*status & FE_HAS_LOCK))
+		st->i2c_talk_onoff = 1;
+
+	return ret;
+}
+
+static int dm04_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
 	struct lme2510_state *st = fe_to_priv(fe);
 
-	*strength = (u16)((u32)st->signal_level * 0xffff / 0xff);
+	if (st->fe_read_signal_strength && !st->stream_on)
+		return st->fe_read_signal_strength(fe, strength);
+
+	switch (st->tuner_config) {
+	case TUNER_LG:
+		*strength = 0xff - st->signal_level;
+		*strength |= *strength << 8;
+		break;
+	/* fall through */
+	case TUNER_S7395:
+	case TUNER_S0194:
+		*strength = 0xffff - (((st->signal_level * 2) << 8) * 5 / 4);
+		break;
+	case TUNER_RS2000:
+		*strength = (u16)((u32)st->signal_level * 0xffff / 0xff);
+	}
 
 	return 0;
 }
 
-static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
+static int dm04_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
 	struct lme2510_state *st = fe_to_priv(fe);
 
-	*snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f);
+	if (st->fe_read_snr && !st->stream_on)
+		return st->fe_read_snr(fe, snr);
+
+	switch (st->tuner_config) {
+	case TUNER_LG:
+		*snr = 0xff - st->signal_sn;
+		*snr |= *snr << 8;
+		break;
+	/* fall through */
+	case TUNER_S7395:
+	case TUNER_S0194:
+		*snr = (u16)((0xff - st->signal_sn - 0xa1) * 3) << 8;
+		break;
+	case TUNER_RS2000:
+		*snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f);
+	}
 
 	return 0;
 }
 
 static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
+	struct lme2510_state *st = fe_to_priv(fe);
+
+	if (st->fe_read_ber && !st->stream_on)
+		return st->fe_read_ber(fe, ber);
+
 	*ber = 0;
 
 	return 0;
@@ -1026,6 +939,11 @@ static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber)
 
 static int dm04_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
+	struct lme2510_state *st = fe_to_priv(fe);
+
+	if (st->fe_read_ucblocks && !st->stream_on)
+		return st->fe_read_ucblocks(fe, ucblocks);
+
 	*ucblocks = 0;
 
 	return 0;
@@ -1119,15 +1037,6 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
 			st->tuner_config = TUNER_RS2000;
 			st->fe_set_voltage =
 				adap->fe[0]->ops.set_voltage;
-
-			adap->fe[0]->ops.read_signal_strength =
-				dm04_rs2000_read_signal_strength;
-			adap->fe[0]->ops.read_snr =
-				dm04_rs2000_read_snr;
-			adap->fe[0]->ops.read_ber =
-				dm04_read_ber;
-			adap->fe[0]->ops.read_ucblocks =
-				dm04_read_ucblocks;
 		}
 		break;
 	}
@@ -1146,7 +1055,19 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
 		return -ENODEV;
 	}
 
+	st->fe_read_status = adap->fe[0]->ops.read_status;
+	st->fe_read_signal_strength = adap->fe[0]->ops.read_signal_strength;
+	st->fe_read_snr = adap->fe[0]->ops.read_snr;
+	st->fe_read_ber = adap->fe[0]->ops.read_ber;
+	st->fe_read_ucblocks = adap->fe[0]->ops.read_ucblocks;
+
+	adap->fe[0]->ops.read_status = dm04_read_status;
+	adap->fe[0]->ops.read_signal_strength = dm04_read_signal_strength;
+	adap->fe[0]->ops.read_snr = dm04_read_snr;
+	adap->fe[0]->ops.read_ber = dm04_read_ber;
+	adap->fe[0]->ops.read_ucblocks = dm04_read_ucblocks;
 	adap->fe[0]->ops.set_voltage = dm04_lme2510_set_voltage;
+
 	ret = lme_name(adap);
 	return ret;
 }
@@ -1288,7 +1209,6 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
 
 	if (st->usb_buffer != NULL) {
 		st->i2c_talk_onoff = 1;
-		st->signal_lock = 0;
 		st->signal_level = 0;
 		st->signal_sn = 0;
 		buffer = st->usb_buffer;
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c
index 0a98d04c53e4..ecefa5c477fa 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c
@@ -604,9 +604,3 @@ MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.1");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
index 2d4530f5be54..0bd83e52669c 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
@@ -47,9 +47,3 @@ struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
 #endif /* CONFIG_DVB_USB_MXL111SF */
 
 #endif /* __MXL111SF_DEMOD_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c
index a619410adde4..2180c13a6dcc 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c
@@ -755,9 +755,3 @@ int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
 	}
 	return 0;
 }
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h
index b85a5772d771..16fa4d4daf88 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h
@@ -48,9 +48,3 @@ int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
 				  enum mxl111sf_mux_config pin_mux_config);
 
 #endif /* _DVB_USB_MXL111SF_GPIO_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
index a101d06eb143..283495c84ba3 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
@@ -842,9 +842,3 @@ int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
 
 	return i == num ? num : -EREMOTEIO;
 }
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h
index 465762145ad2..c486fe02f018 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h
@@ -27,9 +27,3 @@ int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
 		      struct i2c_msg msg[], int num);
 
 #endif /* _DVB_USB_MXL111SF_I2C_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c
index f6b348024bec..5b0191178f9f 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c
@@ -335,9 +335,3 @@ int mxl111sf_idac_config(struct mxl111sf_state *state,
 
 	return ret;
 }
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h
index 0643738de7de..25aa4a1ea755 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h
@@ -45,9 +45,3 @@ int mxl111sf_idac_config(struct mxl111sf_state *state,
 			 u8 current_value, u8 hysteresis_value);
 
 #endif /* _DVB_USB_MXL111SF_PHY_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h
index 89bf115e927e..1f4bfbcdbabb 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h
@@ -171,9 +171,3 @@
 #define V6_DIG_RF_PWR_MSB_REG  0x47
 
 #endif /* _DVB_USB_MXL111SF_REG_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
index a8d2c7053674..444579be0b77 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
@@ -515,11 +515,3 @@ MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.1");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
index 2046db22519e..e6caab21a197 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
@@ -77,12 +77,3 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
 #endif
 
 #endif /* __MXL111SF_TUNER_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index c3447eaf1104..bec12b0e076b 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -1425,9 +1425,3 @@ MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
index 8516c011b7cc..ee70df1f1e94 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
@@ -152,9 +152,3 @@ extern int dvb_usb_mxl111sf_debug;
 })
 
 #endif /* _DVB_USB_MXL111SF_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 896a225ee011..77dcfdf547ac 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -22,42 +22,6 @@
 
 #include "rtl28xxu.h"
 
-#include "rtl2830.h"
-#include "rtl2832.h"
-#include "rtl2832_sdr.h"
-#include "mn88472.h"
-#include "mn88473.h"
-
-#include "qt1010.h"
-#include "mt2060.h"
-#include "mxl5005s.h"
-#include "fc0012.h"
-#include "fc0013.h"
-#include "e4000.h"
-#include "fc2580.h"
-#include "tua9001.h"
-#include "r820t.h"
-
-
-#ifdef CONFIG_MEDIA_ATTACH
-#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
-	void *__r = NULL; \
-	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
-	if (__a) { \
-		__r = (void *) __a(ARGS); \
-		if (__r == NULL) \
-			symbol_put(FUNCTION); \
-	} \
-	__r; \
-})
-
-#else
-#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
-	FUNCTION(ARGS); \
-})
-
-#endif
-
 static int rtl28xxu_disable_rc;
 module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644);
 MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller");
@@ -65,20 +29,14 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
 {
+	struct rtl28xxu_dev *dev = d->priv;
 	int ret;
 	unsigned int pipe;
 	u8 requesttype;
-	u8 *buf;
-
-	buf = kmalloc(req->size, GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto err;
-	}
 
 	if (req->index & CMD_WR_FLAG) {
 		/* write */
-		memcpy(buf, req->data, req->size);
+		memcpy(dev->buf, req->data, req->size);
 		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
 		pipe = usb_sndctrlpipe(d->udev, 0);
 	} else {
@@ -88,30 +46,23 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
 	}
 
 	ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value,
-			req->index, buf, req->size, 1000);
-
+			req->index, dev->buf, req->size, 1000);
 	dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
-			req->index, buf, req->size);
-
-	if (ret > 0)
-		ret = 0;
+			req->index, dev->buf, req->size);
+	if (ret < 0)
+		goto err;
 
 	/* read request, copy returned data to return buf */
-	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
-		memcpy(req->data, buf, req->size);
+	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
+		memcpy(req->data, dev->buf, req->size);
 
-	kfree(buf);
-
-	if (ret)
-		goto err;
-
-	return ret;
+	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
+static int rtl28xxu_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
 {
 	struct rtl28xxu_req req;
 
@@ -129,7 +80,7 @@ static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
 	return rtl28xxu_ctrl_msg(d, &req);
 }
 
-static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
+static int rtl28xxu_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
 {
 	struct rtl28xxu_req req;
 
@@ -147,17 +98,17 @@ static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
 	return rtl28xxu_ctrl_msg(d, &req);
 }
 
-static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
+static int rtl28xxu_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
 {
-	return rtl28xx_wr_regs(d, reg, &val, 1);
+	return rtl28xxu_wr_regs(d, reg, &val, 1);
 }
 
-static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
+static int rtl28xxu_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
 {
-	return rtl2831_rd_regs(d, reg, val, 1);
+	return rtl28xxu_rd_regs(d, reg, val, 1);
 }
 
-static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
+static int rtl28xxu_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
 		u8 mask)
 {
 	int ret;
@@ -165,7 +116,7 @@ static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
 
 	/* no need for read if whole reg is written */
 	if (mask != 0xff) {
-		ret = rtl28xx_rd_reg(d, reg, &tmp);
+		ret = rtl28xxu_rd_reg(d, reg, &tmp);
 		if (ret)
 			return ret;
 
@@ -174,7 +125,7 @@ static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
 		val |= tmp;
 	}
 
-	return rtl28xx_wr_reg(d, reg, val);
+	return rtl28xxu_wr_reg(d, reg, val);
 }
 
 /* I2C */
@@ -183,7 +134,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 {
 	int ret;
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct rtl28xxu_priv *priv = d->priv;
+	struct rtl28xxu_dev *dev = d->priv;
 	struct rtl28xxu_req req;
 
 	/*
@@ -220,7 +171,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 		} else if (msg[0].addr == 0x10) {
 			/* method 1 - integrated demod */
 			req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
-			req.index = CMD_DEMOD_RD | priv->page;
+			req.index = CMD_DEMOD_RD | dev->page;
 			req.size = msg[1].len;
 			req.data = &msg[1].buf[0];
 			ret = rtl28xxu_ctrl_msg(d, &req);
@@ -256,12 +207,12 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 			/* method 1 - integrated demod */
 			if (msg[0].buf[0] == 0x00) {
 				/* save demod page for later demod access */
-				priv->page = msg[0].buf[1];
+				dev->page = msg[0].buf[1];
 				ret = 0;
 			} else {
 				req.value = (msg[0].buf[0] << 8) |
 					(msg[0].addr << 1);
-				req.index = CMD_DEMOD_WR | priv->page;
+				req.index = CMD_DEMOD_WR | dev->page;
 				req.size = msg[0].len-1;
 				req.data = &msg[0].buf[1];
 				ret = rtl28xxu_ctrl_msg(d, &req);
@@ -303,7 +254,7 @@ static struct i2c_algorithm rtl28xxu_i2c_algo = {
 
 static int rtl2831u_read_config(struct dvb_usb_device *d)
 {
-	struct rtl28xxu_priv *priv = d_to_priv(d);
+	struct rtl28xxu_dev *dev = d_to_priv(d);
 	int ret;
 	u8 buf[1];
 	/* open RTL2831U/RTL2830 I2C gate */
@@ -312,7 +263,7 @@ static int rtl2831u_read_config(struct dvb_usb_device *d)
 	struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf};
 	struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf};
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+	dev_dbg(&d->intf->dev, "\n");
 
 	/*
 	 * RTL2831U GPIOs
@@ -323,12 +274,12 @@ static int rtl2831u_read_config(struct dvb_usb_device *d)
 	 */
 
 	/* GPIO direction */
-	ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a);
+	ret = rtl28xxu_wr_reg(d, SYS_GPIO_DIR, 0x0a);
 	if (ret)
 		goto err;
 
 	/* enable as output GPIO0, GPIO2, GPIO4 */
-	ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15);
+	ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_EN, 0x15);
 	if (ret)
 		goto err;
 
@@ -340,7 +291,7 @@ static int rtl2831u_read_config(struct dvb_usb_device *d)
 	/* demod needs some time to wake up */
 	msleep(20);
 
-	priv->tuner_name = "NONE";
+	dev->tuner_name = "NONE";
 
 	/* open demod I2C gate */
 	ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
@@ -350,8 +301,8 @@ static int rtl2831u_read_config(struct dvb_usb_device *d)
 	/* check QT1010 ID(?) register; reg=0f val=2c */
 	ret = rtl28xxu_ctrl_msg(d, &req_qt1010);
 	if (ret == 0 && buf[0] == 0x2c) {
-		priv->tuner = TUNER_RTL2830_QT1010;
-		priv->tuner_name = "QT1010";
+		dev->tuner = TUNER_RTL2830_QT1010;
+		dev->tuner_name = "QT1010";
 		goto found;
 	}
 
@@ -363,28 +314,28 @@ static int rtl2831u_read_config(struct dvb_usb_device *d)
 	/* check MT2060 ID register; reg=00 val=63 */
 	ret = rtl28xxu_ctrl_msg(d, &req_mt2060);
 	if (ret == 0 && buf[0] == 0x63) {
-		priv->tuner = TUNER_RTL2830_MT2060;
-		priv->tuner_name = "MT2060";
+		dev->tuner = TUNER_RTL2830_MT2060;
+		dev->tuner_name = "MT2060";
 		goto found;
 	}
 
 	/* assume MXL5005S */
-	priv->tuner = TUNER_RTL2830_MXL5005S;
-	priv->tuner_name = "MXL5005S";
+	dev->tuner = TUNER_RTL2830_MXL5005S;
+	dev->tuner_name = "MXL5005S";
 	goto found;
 
 found:
-	dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
+	dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name);
 
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
 static int rtl2832u_read_config(struct dvb_usb_device *d)
 {
-	struct rtl28xxu_priv *priv = d_to_priv(d);
+	struct rtl28xxu_dev *dev = d_to_priv(d);
 	int ret;
 	u8 buf[2];
 	/* open RTL2832U/RTL2832 I2C gate */
@@ -407,14 +358,14 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
 	struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf};
 	struct rtl28xxu_req req_mn88473 = {0xff38, CMD_I2C_RD, 1, buf};
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+	dev_dbg(&d->intf->dev, "\n");
 
 	/* enable GPIO3 and GPIO6 as output */
-	ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40);
+	ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40);
 	if (ret)
 		goto err;
 
-	ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48);
+	ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48);
 	if (ret)
 		goto err;
 
@@ -428,134 +379,134 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
 	if (ret)
 		goto err;
 
-	priv->tuner_name = "NONE";
+	dev->tuner_name = "NONE";
 
 	/* check FC0012 ID register; reg=00 val=a1 */
 	ret = rtl28xxu_ctrl_msg(d, &req_fc0012);
 	if (ret == 0 && buf[0] == 0xa1) {
-		priv->tuner = TUNER_RTL2832_FC0012;
-		priv->tuner_name = "FC0012";
+		dev->tuner = TUNER_RTL2832_FC0012;
+		dev->tuner_name = "FC0012";
 		goto tuner_found;
 	}
 
 	/* check FC0013 ID register; reg=00 val=a3 */
 	ret = rtl28xxu_ctrl_msg(d, &req_fc0013);
 	if (ret == 0 && buf[0] == 0xa3) {
-		priv->tuner = TUNER_RTL2832_FC0013;
-		priv->tuner_name = "FC0013";
+		dev->tuner = TUNER_RTL2832_FC0013;
+		dev->tuner_name = "FC0013";
 		goto tuner_found;
 	}
 
 	/* check MT2266 ID register; reg=00 val=85 */
 	ret = rtl28xxu_ctrl_msg(d, &req_mt2266);
 	if (ret == 0 && buf[0] == 0x85) {
-		priv->tuner = TUNER_RTL2832_MT2266;
-		priv->tuner_name = "MT2266";
+		dev->tuner = TUNER_RTL2832_MT2266;
+		dev->tuner_name = "MT2266";
 		goto tuner_found;
 	}
 
 	/* check FC2580 ID register; reg=01 val=56 */
 	ret = rtl28xxu_ctrl_msg(d, &req_fc2580);
 	if (ret == 0 && buf[0] == 0x56) {
-		priv->tuner = TUNER_RTL2832_FC2580;
-		priv->tuner_name = "FC2580";
+		dev->tuner = TUNER_RTL2832_FC2580;
+		dev->tuner_name = "FC2580";
 		goto tuner_found;
 	}
 
 	/* check MT2063 ID register; reg=00 val=9e || 9c */
 	ret = rtl28xxu_ctrl_msg(d, &req_mt2063);
 	if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
-		priv->tuner = TUNER_RTL2832_MT2063;
-		priv->tuner_name = "MT2063";
+		dev->tuner = TUNER_RTL2832_MT2063;
+		dev->tuner_name = "MT2063";
 		goto tuner_found;
 	}
 
 	/* check MAX3543 ID register; reg=00 val=38 */
 	ret = rtl28xxu_ctrl_msg(d, &req_max3543);
 	if (ret == 0 && buf[0] == 0x38) {
-		priv->tuner = TUNER_RTL2832_MAX3543;
-		priv->tuner_name = "MAX3543";
+		dev->tuner = TUNER_RTL2832_MAX3543;
+		dev->tuner_name = "MAX3543";
 		goto tuner_found;
 	}
 
 	/* check TUA9001 ID register; reg=7e val=2328 */
 	ret = rtl28xxu_ctrl_msg(d, &req_tua9001);
 	if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
-		priv->tuner = TUNER_RTL2832_TUA9001;
-		priv->tuner_name = "TUA9001";
+		dev->tuner = TUNER_RTL2832_TUA9001;
+		dev->tuner_name = "TUA9001";
 		goto tuner_found;
 	}
 
 	/* check MXL5007R ID register; reg=d9 val=14 */
 	ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t);
 	if (ret == 0 && buf[0] == 0x14) {
-		priv->tuner = TUNER_RTL2832_MXL5007T;
-		priv->tuner_name = "MXL5007T";
+		dev->tuner = TUNER_RTL2832_MXL5007T;
+		dev->tuner_name = "MXL5007T";
 		goto tuner_found;
 	}
 
 	/* check E4000 ID register; reg=02 val=40 */
 	ret = rtl28xxu_ctrl_msg(d, &req_e4000);
 	if (ret == 0 && buf[0] == 0x40) {
-		priv->tuner = TUNER_RTL2832_E4000;
-		priv->tuner_name = "E4000";
+		dev->tuner = TUNER_RTL2832_E4000;
+		dev->tuner_name = "E4000";
 		goto tuner_found;
 	}
 
 	/* check TDA18272 ID register; reg=00 val=c760  */
 	ret = rtl28xxu_ctrl_msg(d, &req_tda18272);
 	if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
-		priv->tuner = TUNER_RTL2832_TDA18272;
-		priv->tuner_name = "TDA18272";
+		dev->tuner = TUNER_RTL2832_TDA18272;
+		dev->tuner_name = "TDA18272";
 		goto tuner_found;
 	}
 
 	/* check R820T ID register; reg=00 val=69 */
 	ret = rtl28xxu_ctrl_msg(d, &req_r820t);
 	if (ret == 0 && buf[0] == 0x69) {
-		priv->tuner = TUNER_RTL2832_R820T;
-		priv->tuner_name = "R820T";
+		dev->tuner = TUNER_RTL2832_R820T;
+		dev->tuner_name = "R820T";
 		goto tuner_found;
 	}
 
 	/* check R828D ID register; reg=00 val=69 */
 	ret = rtl28xxu_ctrl_msg(d, &req_r828d);
 	if (ret == 0 && buf[0] == 0x69) {
-		priv->tuner = TUNER_RTL2832_R828D;
-		priv->tuner_name = "R828D";
+		dev->tuner = TUNER_RTL2832_R828D;
+		dev->tuner_name = "R828D";
 		goto tuner_found;
 	}
 
 tuner_found:
-	dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
+	dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name);
 
 	/* probe slave demod */
-	if (priv->tuner == TUNER_RTL2832_R828D) {
+	if (dev->tuner == TUNER_RTL2832_R828D) {
 		/* power on MN88472 demod on GPIO0 */
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01);
 		if (ret)
 			goto err;
 
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
 		if (ret)
 			goto err;
 
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
 		if (ret)
 			goto err;
 
 		/* check MN88472 answers */
 		ret = rtl28xxu_ctrl_msg(d, &req_mn88472);
 		if (ret == 0 && buf[0] == 0x02) {
-			dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__);
-			priv->slave_demod = SLAVE_DEMOD_MN88472;
+			dev_dbg(&d->intf->dev, "MN88472 found\n");
+			dev->slave_demod = SLAVE_DEMOD_MN88472;
 			goto demod_found;
 		}
 
 		ret = rtl28xxu_ctrl_msg(d, &req_mn88473);
 		if (ret == 0 && buf[0] == 0x03) {
-			dev_dbg(&d->udev->dev, "%s: MN88473 found\n", __func__);
-			priv->slave_demod = SLAVE_DEMOD_MN88473;
+			dev_dbg(&d->intf->dev, "MN88473 found\n");
+			dev->slave_demod = SLAVE_DEMOD_MN88473;
 			goto demod_found;
 		}
 	}
@@ -568,14 +519,51 @@ demod_found:
 
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static const struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.ts_mode = 0,
+static int rtl28xxu_read_config(struct dvb_usb_device *d)
+{
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U)
+		return rtl2831u_read_config(d);
+	else
+		return rtl2832u_read_config(d);
+}
+
+static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name)
+{
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+	int ret;
+	struct rtl28xxu_req req_demod_i2c = {0x0020, CMD_I2C_DA_RD, 0, NULL};
+
+	dev_dbg(&d->intf->dev, "\n");
+
+	/*
+	 * Detect chip type using I2C command that is not supported
+	 * by old RTL2831U.
+	 */
+	ret = rtl28xxu_ctrl_msg(d, &req_demod_i2c);
+	if (ret == -EPIPE) {
+		dev->chip_id = CHIP_ID_RTL2831U;
+	} else if (ret == 0) {
+		dev->chip_id = CHIP_ID_RTL2832U;
+	} else {
+		dev_err(&d->intf->dev, "chip type detection failed %d\n", ret);
+		goto err;
+	}
+	dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id);
+
+	return WARM;
+err:
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
+	return ret;
+}
+
+static const struct rtl2830_platform_data rtl2830_mt2060_platform_data = {
+	.clk = 28800000,
 	.spec_inv = 1,
 	.vtop = 0x20,
 	.krf = 0x04,
@@ -583,20 +571,16 @@ static const struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
 
 };
 
-static const struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.ts_mode = 0,
+static const struct rtl2830_platform_data rtl2830_qt1010_platform_data = {
+	.clk = 28800000,
 	.spec_inv = 1,
 	.vtop = 0x20,
 	.krf = 0x04,
 	.agc_targ_val = 0x2d,
 };
 
-static const struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.ts_mode = 0,
+static const struct rtl2830_platform_data rtl2830_mxl5005s_platform_data = {
+	.clk = 28800000,
 	.spec_inv = 0,
 	.vtop = 0x3f,
 	.krf = 0x04,
@@ -606,69 +590,81 @@ static const struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
 static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_usb_device *d = adap_to_d(adap);
-	struct rtl28xxu_priv *priv = d_to_priv(d);
-	const struct rtl2830_config *rtl2830_config;
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+	struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data;
+	struct i2c_board_info board_info;
+	struct i2c_client *client;
 	int ret;
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+	dev_dbg(&d->intf->dev, "\n");
 
-	switch (priv->tuner) {
+	switch (dev->tuner) {
 	case TUNER_RTL2830_QT1010:
-		rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
+		*pdata = rtl2830_qt1010_platform_data;
 		break;
 	case TUNER_RTL2830_MT2060:
-		rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
+		*pdata = rtl2830_mt2060_platform_data;
 		break;
 	case TUNER_RTL2830_MXL5005S:
-		rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
+		*pdata = rtl2830_mxl5005s_platform_data;
 		break;
 	default:
-		dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
-				KBUILD_MODNAME, priv->tuner_name);
+		dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name);
 		ret = -ENODEV;
 		goto err;
 	}
 
 	/* attach demodulator */
-	adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap);
-	if (!adap->fe[0]) {
+	memset(&board_info, 0, sizeof(board_info));
+	strlcpy(board_info.type, "rtl2830", I2C_NAME_SIZE);
+	board_info.addr = 0x10;
+	board_info.platform_data = pdata;
+	request_module("%s", board_info.type);
+	client = i2c_new_device(&d->i2c_adap, &board_info);
+	if (client == NULL || client->dev.driver == NULL) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	if (!try_module_get(client->dev.driver->owner)) {
+		i2c_unregister_device(client);
 		ret = -ENODEV;
 		goto err;
 	}
 
+	adap->fe[0] = pdata->get_dvb_frontend(client);
+	dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);
+
+	dev->i2c_client_demod = client;
+
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
+static const struct rtl2832_platform_data rtl2832_fc0012_platform_data = {
+	.clk = 28800000,
 	.tuner = TUNER_RTL2832_FC0012
 };
 
-static const struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
+static const struct rtl2832_platform_data rtl2832_fc0013_platform_data = {
+	.clk = 28800000,
 	.tuner = TUNER_RTL2832_FC0013
 };
 
-static const struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
+static const struct rtl2832_platform_data rtl2832_tua9001_platform_data = {
+	.clk = 28800000,
 	.tuner = TUNER_RTL2832_TUA9001,
 };
 
-static const struct rtl2832_config rtl28xxu_rtl2832_e4000_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
+static const struct rtl2832_platform_data rtl2832_e4000_platform_data = {
+	.clk = 28800000,
 	.tuner = TUNER_RTL2832_E4000,
 };
 
-static const struct rtl2832_config rtl28xxu_rtl2832_r820t_config = {
-	.i2c_addr = 0x10,
-	.xtal = 28800000,
+static const struct rtl2832_platform_data rtl2832_r820t_platform_data = {
+	.clk = 28800000,
 	.tuner = TUNER_RTL2832_R820T,
 };
 
@@ -678,12 +674,12 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
 	int ret;
 	u8 val;
 
-	dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg);
+	dev_dbg(&d->intf->dev, "cmd=%d arg=%d\n", cmd, arg);
 
 	switch (cmd) {
 	case FC_FE_CALLBACK_VHF_ENABLE:
 		/* set output values */
-		ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
+		ret = rtl28xxu_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
 		if (ret)
 			goto err;
 
@@ -693,7 +689,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
 			val |= 0x40; /* set GPIO6 high */
 
 
-		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
+		ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_VAL, val);
 		if (ret)
 			goto err;
 		break;
@@ -703,7 +699,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
 	}
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -713,7 +709,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
 	int ret;
 	u8 val;
 
-	dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg);
+	dev_dbg(&d->intf->dev, "cmd=%d arg=%d\n", cmd, arg);
 
 	/*
 	 * CEN     always enabled by hardware wiring
@@ -728,7 +724,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
 		else
 			val = (0 << 4);
 
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10);
 		if (ret)
 			goto err;
 		break;
@@ -738,7 +734,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
 		else
 			val = (0 << 1);
 
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02);
 		if (ret)
 			goto err;
 		break;
@@ -746,40 +742,46 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
 
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
-{
-	struct rtl28xxu_priv *priv = d->priv;
-
-	switch (priv->tuner) {
-	case TUNER_RTL2832_FC0012:
-		return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
-	case TUNER_RTL2832_TUA9001:
-		return rtl2832u_tua9001_tuner_callback(d, cmd, arg);
-	default:
-		break;
-	}
-
-	return 0;
-}
-
 static int rtl2832u_frontend_callback(void *adapter_priv, int component,
 		int cmd, int arg)
 {
-	struct i2c_adapter *adap = adapter_priv;
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct i2c_adapter *adapter = adapter_priv;
+	struct device *parent = adapter->dev.parent;
+	struct i2c_adapter *parent_adapter;
+	struct dvb_usb_device *d;
+	struct rtl28xxu_dev *dev;
+
+	/*
+	 * All tuners are connected to demod muxed I2C adapter. We have to
+	 * resolve its parent adapter in order to get handle for this driver
+	 * private data. That is a bit hackish solution, GPIO or direct driver
+	 * callback would be better...
+	 */
+	if (parent != NULL && parent->type == &i2c_adapter_type)
+		parent_adapter = to_i2c_adapter(parent);
+	else
+		return -EINVAL;
+
+	d = i2c_get_adapdata(parent_adapter);
+	dev = d->priv;
 
-	dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n",
-			__func__, component, cmd, arg);
+	dev_dbg(&d->intf->dev, "component=%d cmd=%d arg=%d\n",
+		component, cmd, arg);
 
 	switch (component) {
 	case DVB_FRONTEND_COMPONENT_TUNER:
-		return rtl2832u_tuner_callback(d, cmd, arg);
+		switch (dev->tuner) {
+		case TUNER_RTL2832_FC0012:
+			return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
+		case TUNER_RTL2832_TUA9001:
+			return rtl2832u_tua9001_tuner_callback(d, cmd, arg);
+		}
 	default:
-		break;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -787,57 +789,70 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component,
 
 static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	int ret;
 	struct dvb_usb_device *d = adap_to_d(adap);
-	struct rtl28xxu_priv *priv = d_to_priv(d);
-	const struct rtl2832_config *rtl2832_config;
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+	struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
+	struct i2c_board_info board_info;
+	struct i2c_client *client;
+	int ret;
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+	dev_dbg(&d->intf->dev, "\n");
 
-	switch (priv->tuner) {
+	switch (dev->tuner) {
 	case TUNER_RTL2832_FC0012:
-		rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
+		*pdata = rtl2832_fc0012_platform_data;
 		break;
 	case TUNER_RTL2832_FC0013:
-		rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
+		*pdata = rtl2832_fc0013_platform_data;
 		break;
 	case TUNER_RTL2832_FC2580:
 		/* FIXME: do not abuse fc0012 settings */
-		rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
+		*pdata = rtl2832_fc0012_platform_data;
 		break;
 	case TUNER_RTL2832_TUA9001:
-		rtl2832_config = &rtl28xxu_rtl2832_tua9001_config;
+		*pdata = rtl2832_tua9001_platform_data;
 		break;
 	case TUNER_RTL2832_E4000:
-		rtl2832_config = &rtl28xxu_rtl2832_e4000_config;
+		*pdata = rtl2832_e4000_platform_data;
 		break;
 	case TUNER_RTL2832_R820T:
 	case TUNER_RTL2832_R828D:
-		rtl2832_config = &rtl28xxu_rtl2832_r820t_config;
+		*pdata = rtl2832_r820t_platform_data;
 		break;
 	default:
-		dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
-				KBUILD_MODNAME, priv->tuner_name);
+		dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name);
 		ret = -ENODEV;
 		goto err;
 	}
 
 	/* attach demodulator */
-	adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, &d->i2c_adap);
-	if (!adap->fe[0]) {
+	memset(&board_info, 0, sizeof(board_info));
+	strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
+	board_info.addr = 0x10;
+	board_info.platform_data = pdata;
+	request_module("%s", board_info.type);
+	client = i2c_new_device(&d->i2c_adap, &board_info);
+	if (client == NULL || client->dev.driver == NULL) {
 		ret = -ENODEV;
 		goto err;
 	}
 
-	/* RTL2832 I2C repeater */
-	priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]);
+	if (!try_module_get(client->dev.driver->owner)) {
+		i2c_unregister_device(client);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	adap->fe[0] = pdata->get_dvb_frontend(client);
+	dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);
+
+	dev->i2c_client_demod = client;
 
 	/* set fe callback */
 	adap->fe[0]->callback = rtl2832u_frontend_callback;
 
-	if (priv->slave_demod) {
+	if (dev->slave_demod) {
 		struct i2c_board_info info = {};
-		struct i2c_client *client;
 
 		/*
 		 * We continue on reduced mode, without DVB-T2/C, using master
@@ -846,28 +861,29 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
 		ret = 0;
 
 		/* attach slave demodulator */
-		if (priv->slave_demod == SLAVE_DEMOD_MN88472) {
+		if (dev->slave_demod == SLAVE_DEMOD_MN88472) {
 			struct mn88472_config mn88472_config = {};
 
 			mn88472_config.fe = &adap->fe[1];
 			mn88472_config.i2c_wr_max = 22,
 			strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
+			mn88472_config.xtal = 20500000;
 			info.addr = 0x18;
 			info.platform_data = &mn88472_config;
 			request_module(info.type);
-			client = i2c_new_device(priv->demod_i2c_adapter, &info);
+			client = i2c_new_device(&d->i2c_adap, &info);
 			if (client == NULL || client->dev.driver == NULL) {
-				priv->slave_demod = SLAVE_DEMOD_NONE;
+				dev->slave_demod = SLAVE_DEMOD_NONE;
 				goto err_slave_demod_failed;
 			}
 
 			if (!try_module_get(client->dev.driver->owner)) {
 				i2c_unregister_device(client);
-				priv->slave_demod = SLAVE_DEMOD_NONE;
+				dev->slave_demod = SLAVE_DEMOD_NONE;
 				goto err_slave_demod_failed;
 			}
 
-			priv->i2c_client_slave_demod = client;
+			dev->i2c_client_slave_demod = client;
 		} else {
 			struct mn88473_config mn88473_config = {};
 
@@ -877,29 +893,64 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
 			info.addr = 0x18;
 			info.platform_data = &mn88473_config;
 			request_module(info.type);
-			client = i2c_new_device(priv->demod_i2c_adapter, &info);
+			client = i2c_new_device(&d->i2c_adap, &info);
 			if (client == NULL || client->dev.driver == NULL) {
-				priv->slave_demod = SLAVE_DEMOD_NONE;
+				dev->slave_demod = SLAVE_DEMOD_NONE;
 				goto err_slave_demod_failed;
 			}
 
 			if (!try_module_get(client->dev.driver->owner)) {
 				i2c_unregister_device(client);
-				priv->slave_demod = SLAVE_DEMOD_NONE;
+				dev->slave_demod = SLAVE_DEMOD_NONE;
 				goto err_slave_demod_failed;
 			}
 
-			priv->i2c_client_slave_demod = client;
+			dev->i2c_client_slave_demod = client;
 		}
 	}
 
 	return 0;
 err_slave_demod_failed:
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
+static int rtl28xxu_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct rtl28xxu_dev *dev = adap_to_priv(adap);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U)
+		return rtl2831u_frontend_attach(adap);
+	else
+		return rtl2832u_frontend_attach(adap);
+}
+
+static int rtl28xxu_frontend_detach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap_to_d(adap);
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+	struct i2c_client *client;
+
+	dev_dbg(&d->intf->dev, "\n");
+
+	/* remove I2C slave demod */
+	client = dev->i2c_client_slave_demod;
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
+
+	/* remove I2C demod */
+	client = dev->i2c_client_demod;
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
+
+	return 0;
+}
+
 static struct qt1010_config rtl28xxu_qt1010_config = {
 	.i2c_address = 0x62, /* 0xc4 */
 };
@@ -930,33 +981,30 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	int ret;
 	struct dvb_usb_device *d = adap_to_d(adap);
-	struct rtl28xxu_priv *priv = d_to_priv(d);
-	struct i2c_adapter *rtl2830_tuner_i2c;
+	struct rtl28xxu_dev *dev = d_to_priv(d);
 	struct dvb_frontend *fe;
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
-
-	/* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */
-	rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]);
+	dev_dbg(&d->intf->dev, "\n");
 
-	switch (priv->tuner) {
+	switch (dev->tuner) {
 	case TUNER_RTL2830_QT1010:
 		fe = dvb_attach(qt1010_attach, adap->fe[0],
-				rtl2830_tuner_i2c, &rtl28xxu_qt1010_config);
+				dev->demod_i2c_adapter,
+				&rtl28xxu_qt1010_config);
 		break;
 	case TUNER_RTL2830_MT2060:
 		fe = dvb_attach(mt2060_attach, adap->fe[0],
-				rtl2830_tuner_i2c, &rtl28xxu_mt2060_config,
-				1220);
+				dev->demod_i2c_adapter,
+				&rtl28xxu_mt2060_config, 1220);
 		break;
 	case TUNER_RTL2830_MXL5005S:
 		fe = dvb_attach(mxl5005s_attach, adap->fe[0],
-				rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config);
+				dev->demod_i2c_adapter,
+				&rtl28xxu_mxl5005s_config);
 		break;
 	default:
 		fe = NULL;
-		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
-				priv->tuner);
+		dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner);
 	}
 
 	if (fe == NULL) {
@@ -966,7 +1014,7 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
 
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -1002,45 +1050,38 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	int ret;
 	struct dvb_usb_device *d = adap_to_d(adap);
-	struct rtl28xxu_priv *priv = d_to_priv(d);
+	struct rtl28xxu_dev *dev = d_to_priv(d);
 	struct dvb_frontend *fe = NULL;
 	struct i2c_board_info info;
 	struct i2c_client *client;
+	struct v4l2_subdev *subdev = NULL;
+	struct platform_device *pdev;
+	struct rtl2832_sdr_platform_data pdata;
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+	dev_dbg(&d->intf->dev, "\n");
 
 	memset(&info, 0, sizeof(struct i2c_board_info));
+	memset(&pdata, 0, sizeof(pdata));
 
-	switch (priv->tuner) {
+	switch (dev->tuner) {
 	case TUNER_RTL2832_FC0012:
 		fe = dvb_attach(fc0012_attach, adap->fe[0],
-			&d->i2c_adap, &rtl2832u_fc0012_config);
+			dev->demod_i2c_adapter, &rtl2832u_fc0012_config);
 
 		/* since fc0012 includs reading the signal strength delegate
 		 * that to the tuner driver */
 		adap->fe[0]->ops.read_signal_strength =
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
-		/* attach SDR */
-		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
-				&rtl28xxu_rtl2832_fc0012_config, NULL);
 		break;
 	case TUNER_RTL2832_FC0013:
 		fe = dvb_attach(fc0013_attach, adap->fe[0],
-			&d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
+			dev->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
 
 		/* fc0013 also supports signal strength reading */
 		adap->fe[0]->ops.read_signal_strength =
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
-		/* attach SDR */
-		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
-				&rtl28xxu_rtl2832_fc0013_config, NULL);
 		break;
 	case TUNER_RTL2832_E4000: {
-			struct v4l2_subdev *sd;
-			struct i2c_adapter *i2c_adap_internal =
-					rtl2832_get_private_i2c_adapter(adap->fe[0]);
 			struct e4000_config e4000_config = {
 				.fe = adap->fe[0],
 				.clock = 28800000,
@@ -1051,7 +1092,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 			info.platform_data = &e4000_config;
 
 			request_module(info.type);
-			client = i2c_new_device(priv->demod_i2c_adapter, &info);
+			client = i2c_new_device(dev->demod_i2c_adapter, &info);
 			if (client == NULL || client->dev.driver == NULL)
 				break;
 
@@ -1060,157 +1101,183 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 				break;
 			}
 
-			priv->i2c_client_tuner = client;
-			sd = i2c_get_clientdata(client);
-			i2c_set_adapdata(i2c_adap_internal, d);
-
-			/* attach SDR */
-			dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0],
-					i2c_adap_internal,
-					&rtl28xxu_rtl2832_e4000_config, sd);
+			dev->i2c_client_tuner = client;
+			subdev = i2c_get_clientdata(client);
 		}
 		break;
 	case TUNER_RTL2832_FC2580:
-		fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap,
+		fe = dvb_attach(fc2580_attach, adap->fe[0],
+				dev->demod_i2c_adapter,
 				&rtl2832u_fc2580_config);
 		break;
 	case TUNER_RTL2832_TUA9001:
 		/* enable GPIO1 and GPIO4 as output */
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
 		if (ret)
 			goto err;
 
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
 		if (ret)
 			goto err;
 
-		fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap,
+		fe = dvb_attach(tua9001_attach, adap->fe[0],
+				dev->demod_i2c_adapter,
 				&rtl2832u_tua9001_config);
 		break;
 	case TUNER_RTL2832_R820T:
-		fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap,
+		fe = dvb_attach(r820t_attach, adap->fe[0],
+				dev->demod_i2c_adapter,
 				&rtl2832u_r820t_config);
 
 		/* Use tuner to get the signal strength */
 		adap->fe[0]->ops.read_signal_strength =
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
-		/* attach SDR */
-		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
-				&rtl28xxu_rtl2832_r820t_config, NULL);
 		break;
 	case TUNER_RTL2832_R828D:
 		fe = dvb_attach(r820t_attach, adap->fe[0],
-				priv->demod_i2c_adapter,
+				dev->demod_i2c_adapter,
 				&rtl2832u_r828d_config);
 		adap->fe[0]->ops.read_signal_strength =
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
 		if (adap->fe[1]) {
 			fe = dvb_attach(r820t_attach, adap->fe[1],
-					priv->demod_i2c_adapter,
+					dev->demod_i2c_adapter,
 					&rtl2832u_r828d_config);
 			adap->fe[1]->ops.read_signal_strength =
 					adap->fe[1]->ops.tuner_ops.get_rf_strength;
 		}
-
-		/* attach SDR */
-		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
-				&rtl28xxu_rtl2832_r820t_config, NULL);
 		break;
 	default:
-		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
-				priv->tuner);
+		dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner);
 	}
-
-	if (fe == NULL && priv->i2c_client_tuner == NULL) {
+	if (fe == NULL && dev->i2c_client_tuner == NULL) {
 		ret = -ENODEV;
 		goto err;
 	}
 
+	/* register SDR */
+	switch (dev->tuner) {
+	case TUNER_RTL2832_FC0012:
+	case TUNER_RTL2832_FC0013:
+	case TUNER_RTL2832_E4000:
+	case TUNER_RTL2832_R820T:
+	case TUNER_RTL2832_R828D:
+		pdata.clk = dev->rtl2832_platform_data.clk;
+		pdata.tuner = dev->tuner;
+		pdata.i2c_client = dev->i2c_client_demod;
+		pdata.bulk_read = dev->rtl2832_platform_data.bulk_read;
+		pdata.bulk_write = dev->rtl2832_platform_data.bulk_write;
+		pdata.update_bits = dev->rtl2832_platform_data.update_bits;
+		pdata.dvb_frontend = adap->fe[0];
+		pdata.dvb_usb_device = d;
+		pdata.v4l2_subdev = subdev;
+
+		request_module("%s", "rtl2832_sdr");
+		pdev = platform_device_register_data(&d->intf->dev,
+						     "rtl2832_sdr",
+						     PLATFORM_DEVID_AUTO,
+						     &pdata, sizeof(pdata));
+		if (pdev == NULL || pdev->dev.driver == NULL)
+			break;
+		dev->platform_device_sdr = pdev;
+		break;
+	default:
+		dev_dbg(&d->intf->dev, "no SDR for tuner=%d\n", dev->tuner);
+	}
+
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
+static int rtl28xxu_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct rtl28xxu_dev *dev = adap_to_priv(adap);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U)
+		return rtl2831u_tuner_attach(adap);
+	else
+		return rtl2832u_tuner_attach(adap);
+}
+
+static int rtl28xxu_tuner_detach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap_to_d(adap);
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+	struct i2c_client *client;
+	struct platform_device *pdev;
+
+	dev_dbg(&d->intf->dev, "\n");
+
+	/* remove platform SDR */
+	pdev = dev->platform_device_sdr;
+	if (pdev)
+		platform_device_unregister(pdev);
+
+	/* remove I2C tuner */
+	client = dev->i2c_client_tuner;
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
+
+	return 0;
+}
+
 static int rtl28xxu_init(struct dvb_usb_device *d)
 {
 	int ret;
 	u8 val;
 
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+	dev_dbg(&d->intf->dev, "\n");
 
 	/* init USB endpoints */
-	ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
+	ret = rtl28xxu_rd_reg(d, USB_SYSCTL_0, &val);
 	if (ret)
 		goto err;
 
 	/* enable DMA and Full Packet Mode*/
 	val |= 0x09;
-	ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
+	ret = rtl28xxu_wr_reg(d, USB_SYSCTL_0, val);
 	if (ret)
 		goto err;
 
 	/* set EPA maximum packet size to 0x0200 */
-	ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
+	ret = rtl28xxu_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
 	if (ret)
 		goto err;
 
 	/* change EPA FIFO length */
-	ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
+	ret = rtl28xxu_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
 	if (ret)
 		goto err;
 
 	return ret;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static void rtl28xxu_exit(struct dvb_usb_device *d)
-{
-	struct rtl28xxu_priv *priv = d->priv;
-	struct i2c_client *client;
-
-	dev_dbg(&d->udev->dev, "%s:\n", __func__);
-
-	/* remove I2C tuner */
-	client = priv->i2c_client_tuner;
-	if (client) {
-		module_put(client->dev.driver->owner);
-		i2c_unregister_device(client);
-	}
-
-	/* remove I2C slave demod */
-	client = priv->i2c_client_slave_demod;
-	if (client) {
-		module_put(client->dev.driver->owner);
-		i2c_unregister_device(client);
-	}
-
-	return;
-}
-
 static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
 	int ret;
 	u8 gpio, sys0, epa_ctl[2];
 
-	dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
+	dev_dbg(&d->intf->dev, "onoff=%d\n", onoff);
 
 	/* demod adc */
-	ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0);
+	ret = rtl28xxu_rd_reg(d, SYS_SYS0, &sys0);
 	if (ret)
 		goto err;
 
 	/* tuner power, read GPIOs */
-	ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
+	ret = rtl28xxu_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
 	if (ret)
 		goto err;
 
-	dev_dbg(&d->udev->dev, "%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__,
-			sys0, gpio);
+	dev_dbg(&d->intf->dev, "RD SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio);
 
 	if (onoff) {
 		gpio |= 0x01; /* GPIO0 = 1 */
@@ -1229,21 +1296,20 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
 		epa_ctl[1] = 0x02; /* set reset */
 	}
 
-	dev_dbg(&d->udev->dev, "%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__,
-			sys0, gpio);
+	dev_dbg(&d->intf->dev, "WR SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio);
 
 	/* demod adc */
-	ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0);
+	ret = rtl28xxu_wr_reg(d, SYS_SYS0, sys0);
 	if (ret)
 		goto err;
 
 	/* tuner power, write GPIOs */
-	ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
+	ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
 	if (ret)
 		goto err;
 
 	/* streaming EP: stall & reset */
-	ret = rtl28xx_wr_regs(d, USB_EPA_CTL, epa_ctl, 2);
+	ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, epa_ctl, 2);
 	if (ret)
 		goto err;
 
@@ -1252,7 +1318,7 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
 
 	return ret;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -1260,31 +1326,31 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
 	int ret;
 
-	dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
+	dev_dbg(&d->intf->dev, "onoff=%d\n", onoff);
 
 	if (onoff) {
 		/* GPIO3=1, GPIO4=0 */
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18);
 		if (ret)
 			goto err;
 
 		/* suspend? */
-		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10);
 		if (ret)
 			goto err;
 
 		/* enable PLL */
-		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80);
 		if (ret)
 			goto err;
 
 		/* disable reset */
-		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20);
 		if (ret)
 			goto err;
 
 		/* streaming EP: clear stall & reset */
-		ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
+		ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
 		if (ret)
 			goto err;
 
@@ -1293,35 +1359,49 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
 			goto err;
 	} else {
 		/* GPIO4=1 */
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10);
 		if (ret)
 			goto err;
 
 		/* disable PLL */
-		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80);
+		ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80);
 		if (ret)
 			goto err;
 
 		/* streaming EP: set stall & reset */
-		ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2);
+		ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2);
 		if (ret)
 			goto err;
 	}
 
 	return ret;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
-static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff)
+static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U)
+		return rtl2831u_power_ctrl(d, onoff);
+	else
+		return rtl2832u_power_ctrl(d, onoff);
+}
+
+static int rtl28xxu_frontend_ctrl(struct dvb_frontend *fe, int onoff)
 {
 	struct dvb_usb_device *d = fe_to_d(fe);
-	struct dvb_usb_adapter *adap = fe_to_adap(fe);
+	struct rtl28xxu_dev *dev = fe_to_priv(fe);
+	struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
 	int ret;
 	u8 val;
 
-	dev_dbg(&d->udev->dev, "%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+	dev_dbg(&d->intf->dev, "fe=%d onoff=%d\n", fe->id, onoff);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U)
+		return 0;
 
 	/* control internal demod ADC */
 	if (fe->id == 0 && onoff)
@@ -1329,20 +1409,20 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff)
 	else
 		val = 0x00; /* disable ADC */
 
-	ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48);
+	ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48);
 	if (ret)
 		goto err;
 
 	/* bypass slave demod TS through master demod */
 	if (fe->id == 1 && onoff) {
-		ret = rtl2832_enable_external_ts_if(adap->fe[0]);
+		ret = pdata->enable_slave_ts(dev->i2c_client_demod);
 		if (ret)
 			goto err;
 	}
 
 	return 0;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -1350,7 +1430,7 @@ err:
 static int rtl2831u_rc_query(struct dvb_usb_device *d)
 {
 	int ret, i;
-	struct rtl28xxu_priv *priv = d->priv;
+	struct rtl28xxu_dev *dev = d->priv;
 	u8 buf[5];
 	u32 rc_code;
 	struct rtl28xxu_reg_val rc_nec_tab[] = {
@@ -1371,17 +1451,17 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
 	};
 
 	/* init remote controller */
-	if (!priv->rc_active) {
+	if (!dev->rc_active) {
 		for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
-			ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
+			ret = rtl28xxu_wr_reg(d, rc_nec_tab[i].reg,
 					rc_nec_tab[i].val);
 			if (ret)
 				goto err;
 		}
-		priv->rc_active = true;
+		dev->rc_active = true;
 	}
 
-	ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5);
+	ret = rtl28xxu_rd_regs(d, SYS_IRRC_RP, buf, 5);
 	if (ret)
 		goto err;
 
@@ -1403,19 +1483,19 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
 
 		rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0);
 
-		ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
+		ret = rtl28xxu_wr_reg(d, SYS_IRRC_SR, 1);
 		if (ret)
 			goto err;
 
 		/* repeated intentionally to avoid extra keypress */
-		ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
+		ret = rtl28xxu_wr_reg(d, SYS_IRRC_SR, 1);
 		if (ret)
 			goto err;
 	}
 
 	return ret;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -1433,7 +1513,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
 static int rtl2832u_rc_query(struct dvb_usb_device *d)
 {
 	int ret, i, len;
-	struct rtl28xxu_priv *priv = d->priv;
+	struct rtl28xxu_dev *dev = d->priv;
 	struct ir_raw_event ev;
 	u8 buf[128];
 	static const struct rtl28xxu_reg_val_mask refresh_tab[] = {
@@ -1443,7 +1523,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 	};
 
 	/* init remote controller */
-	if (!priv->rc_active) {
+	if (!dev->rc_active) {
 		static const struct rtl28xxu_reg_val_mask init_tab[] = {
 			{SYS_DEMOD_CTL1,         0x00, 0x04},
 			{SYS_DEMOD_CTL1,         0x00, 0x08},
@@ -1464,36 +1544,36 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 		};
 
 		for (i = 0; i < ARRAY_SIZE(init_tab); i++) {
-			ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg,
+			ret = rtl28xxu_wr_reg_mask(d, init_tab[i].reg,
 					init_tab[i].val, init_tab[i].mask);
 			if (ret)
 				goto err;
 		}
 
-		priv->rc_active = true;
+		dev->rc_active = true;
 	}
 
-	ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]);
+	ret = rtl28xxu_rd_reg(d, IR_RX_IF, &buf[0]);
 	if (ret)
 		goto err;
 
 	if (buf[0] != 0x83)
 		goto exit;
 
-	ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
+	ret = rtl28xxu_rd_reg(d, IR_RX_BC, &buf[0]);
 	if (ret)
 		goto err;
 
 	len = buf[0];
 
 	/* read raw code from hw */
-	ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len);
+	ret = rtl28xxu_rd_regs(d, IR_RX_BUF, buf, len);
 	if (ret)
 		goto err;
 
 	/* let hw receive new code */
 	for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) {
-		ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg,
+		ret = rtl28xxu_wr_reg_mask(d, refresh_tab[i].reg,
 				refresh_tab[i].val, refresh_tab[i].mask);
 		if (ret)
 			goto err;
@@ -1514,7 +1594,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 exit:
 	return ret;
 err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
@@ -1523,7 +1603,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
 {
 	/* disable IR interrupts in order to avoid SDR sample loss */
 	if (rtl28xxu_disable_rc)
-		return rtl28xx_wr_reg(d, IR_RX_IE, 0x00);
+		return rtl28xxu_wr_reg(d, IR_RX_IE, 0x00);
 
 	/* load empty to enable rc */
 	if (!rc->map_name)
@@ -1535,52 +1615,80 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
 
 	return 0;
 }
+
+static int rtl28xxu_get_rc_config(struct dvb_usb_device *d,
+		struct dvb_usb_rc *rc)
+{
+	struct rtl28xxu_dev *dev = d_to_priv(d);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U)
+		return rtl2831u_get_rc_config(d, rc);
+	else
+		return rtl2832u_get_rc_config(d, rc);
+}
 #else
-#define rtl2831u_get_rc_config NULL
-#define rtl2832u_get_rc_config NULL
+#define rtl28xxu_get_rc_config NULL
 #endif
 
-static const struct dvb_usb_device_properties rtl2831u_props = {
-	.driver_name = KBUILD_MODNAME,
-	.owner = THIS_MODULE,
-	.adapter_nr = adapter_nr,
-	.size_of_priv = sizeof(struct rtl28xxu_priv),
+static int rtl28xxu_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct rtl28xxu_dev *dev = adap_to_priv(adap);
 
-	.power_ctrl = rtl2831u_power_ctrl,
-	.i2c_algo = &rtl28xxu_i2c_algo,
-	.read_config = rtl2831u_read_config,
-	.frontend_attach = rtl2831u_frontend_attach,
-	.tuner_attach = rtl2831u_tuner_attach,
-	.init = rtl28xxu_init,
-	.get_rc_config = rtl2831u_get_rc_config,
+	if (dev->chip_id == CHIP_ID_RTL2831U) {
+		struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data;
 
-	.num_adapters = 1,
-	.adapter = {
-		{
-			.stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512),
-		},
-	},
-};
+		return pdata->pid_filter_ctrl(adap->fe[0], onoff);
+	} else {
+		struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
 
-static const struct dvb_usb_device_properties rtl2832u_props = {
+		return pdata->pid_filter_ctrl(adap->fe[0], onoff);
+	}
+}
+
+static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index,
+			       u16 pid, int onoff)
+{
+	struct rtl28xxu_dev *dev = adap_to_priv(adap);
+
+	if (dev->chip_id == CHIP_ID_RTL2831U) {
+		struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data;
+
+		return pdata->pid_filter(adap->fe[0], index, pid, onoff);
+	} else {
+		struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
+
+		return pdata->pid_filter(adap->fe[0], index, pid, onoff);
+	}
+}
+
+static const struct dvb_usb_device_properties rtl28xxu_props = {
 	.driver_name = KBUILD_MODNAME,
 	.owner = THIS_MODULE,
 	.adapter_nr = adapter_nr,
-	.size_of_priv = sizeof(struct rtl28xxu_priv),
+	.size_of_priv = sizeof(struct rtl28xxu_dev),
 
-	.power_ctrl = rtl2832u_power_ctrl,
-	.frontend_ctrl = rtl2832u_frontend_ctrl,
+	.identify_state = rtl28xxu_identify_state,
+	.power_ctrl = rtl28xxu_power_ctrl,
+	.frontend_ctrl = rtl28xxu_frontend_ctrl,
 	.i2c_algo = &rtl28xxu_i2c_algo,
-	.read_config = rtl2832u_read_config,
-	.frontend_attach = rtl2832u_frontend_attach,
-	.tuner_attach = rtl2832u_tuner_attach,
+	.read_config = rtl28xxu_read_config,
+	.frontend_attach = rtl28xxu_frontend_attach,
+	.frontend_detach = rtl28xxu_frontend_detach,
+	.tuner_attach = rtl28xxu_tuner_attach,
+	.tuner_detach = rtl28xxu_tuner_detach,
 	.init = rtl28xxu_init,
-	.exit = rtl28xxu_exit,
-	.get_rc_config = rtl2832u_get_rc_config,
+	.get_rc_config = rtl28xxu_get_rc_config,
 
 	.num_adapters = 1,
 	.adapter = {
 		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER |
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+			.pid_filter_count = 32,
+			.pid_filter_ctrl = rtl28xxu_pid_filter_ctrl,
+			.pid_filter = rtl28xxu_pid_filter,
+
 			.stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512),
 		},
 	},
@@ -1589,69 +1697,69 @@ static const struct dvb_usb_device_properties rtl2832u_props = {
 static const struct usb_device_id rtl28xxu_id_table[] = {
 	/* RTL2831U devices: */
 	{ DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U,
-		&rtl2831u_props, "Realtek RTL2831U reference design", NULL) },
+		&rtl28xxu_props, "Realtek RTL2831U reference design", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT,
-		&rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) },
+		&rtl28xxu_props, "Freecom USB2.0 DVB-T", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2,
-		&rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) },
+		&rtl28xxu_props, "Freecom USB2.0 DVB-T", NULL) },
 
 	/* RTL2832U devices: */
 	{ DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832,
-		&rtl2832u_props, "Realtek RTL2832U reference design", NULL) },
+		&rtl28xxu_props, "Realtek RTL2832U reference design", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838,
-		&rtl2832u_props, "Realtek RTL2832U reference design", NULL) },
+		&rtl28xxu_props, "Realtek RTL2832U reference design", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1,
-		&rtl2832u_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) },
+		&rtl28xxu_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) },
 	{ DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT,
-		&rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) },
+		&rtl28xxu_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK,
-		&rtl2832u_props, "TerraTec NOXON DAB Stick", NULL) },
+		&rtl28xxu_props, "TerraTec NOXON DAB Stick", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV2,
-		&rtl2832u_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) },
+		&rtl28xxu_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV3,
-		&rtl2832u_props, "TerraTec NOXON DAB Stick (rev 3)", NULL) },
+		&rtl28xxu_props, "TerraTec NOXON DAB Stick (rev 3)", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0,
-		&rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) },
+		&rtl28xxu_props, "Trekstor DVB-T Stick Terres 2.0", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101,
-		&rtl2832u_props, "Dexatek DK DVB-T Dongle", NULL) },
+		&rtl28xxu_props, "Dexatek DK DVB-T Dongle", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680,
-		&rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
+		&rtl28xxu_props, "DigitalNow Quad DVB-T Receiver", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINID,
-		&rtl2832u_props, "Leadtek Winfast DTV Dongle Mini D", NULL) },
+		&rtl28xxu_props, "Leadtek Winfast DTV Dongle Mini D", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
-		&rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
+		&rtl28xxu_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
-		&rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) },
+		&rtl28xxu_props, "Dexatek DK mini DVB-T Dongle", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
-		&rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) },
+		&rtl28xxu_props, "TerraTec Cinergy T Stick+", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd3a8,
-		&rtl2832u_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) },
+		&rtl28xxu_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393,
-		&rtl2832u_props, "GIGABYTE U7300", NULL) },
+		&rtl28xxu_props, "GIGABYTE U7300", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104,
-		&rtl2832u_props, "MSI DIGIVOX Micro HD", NULL) },
+		&rtl28xxu_props, "MSI DIGIVOX Micro HD", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620,
-		&rtl2832u_props, "Compro VideoMate U620F", NULL) },
+		&rtl28xxu_props, "Compro VideoMate U620F", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394,
-		&rtl2832u_props, "MaxMedia HU394-T", NULL) },
+		&rtl28xxu_props, "MaxMedia HU394-T", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03,
-		&rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) },
+		&rtl28xxu_props, "Leadtek WinFast DTV Dongle mini", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A,
-		&rtl2832u_props, "Crypto ReDi PC 50 A", NULL) },
+		&rtl28xxu_props, "Crypto ReDi PC 50 A", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KYE, 0x707f,
-		&rtl2832u_props, "Genius TVGo DVB-T03", NULL) },
+		&rtl28xxu_props, "Genius TVGo DVB-T03", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd395,
-		&rtl2832u_props, "Peak DVB-T USB", NULL) },
+		&rtl28xxu_props, "Peak DVB-T USB", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U,
-		&rtl2832u_props, "Sveon STV20", NULL) },
+		&rtl28xxu_props, "Sveon STV20", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV21,
-		&rtl2832u_props, "Sveon STV21", NULL) },
+		&rtl28xxu_props, "Sveon STV21", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27,
-		&rtl2832u_props, "Sveon STV27", NULL) },
+		&rtl28xxu_props, "Sveon STV27", NULL) },
 
 	/* RTL2832P devices: */
 	{ DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131,
-		&rtl2832u_props, "Astrometa DVB-T2", NULL) },
+		&rtl28xxu_props, "Astrometa DVB-T2", NULL) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 3e3ea9d64a38..1b5d7ffb685e 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -22,8 +22,26 @@
 #ifndef RTL28XXU_H
 #define RTL28XXU_H
 
+#include <linux/platform_device.h>
+
 #include "dvb_usb.h"
 
+#include "rtl2830.h"
+#include "rtl2832.h"
+#include "rtl2832_sdr.h"
+#include "mn88472.h"
+#include "mn88473.h"
+
+#include "qt1010.h"
+#include "mt2060.h"
+#include "mxl5005s.h"
+#include "fc0012.h"
+#include "fc0013.h"
+#include "e4000.h"
+#include "fc2580.h"
+#include "tua9001.h"
+#include "r820t.h"
+
 /*
  * USB commands
  * (usb_control_msg() index parameter)
@@ -50,19 +68,26 @@
 #define CMD_I2C_DA_WR    0x0610
 
 
-struct rtl28xxu_priv {
+struct rtl28xxu_dev {
+	u8 buf[28];
 	u8 chip_id;
 	u8 tuner;
 	char *tuner_name;
 	u8 page; /* integrated demod active register page */
 	struct i2c_adapter *demod_i2c_adapter;
 	bool rc_active;
+	struct i2c_client *i2c_client_demod;
 	struct i2c_client *i2c_client_tuner;
 	struct i2c_client *i2c_client_slave_demod;
+	struct platform_device *platform_device_sdr;
 	#define SLAVE_DEMOD_NONE           0
 	#define SLAVE_DEMOD_MN88472        1
 	#define SLAVE_DEMOD_MN88473        2
 	unsigned int slave_demod:2;
+	union {
+		struct rtl2830_platform_data rtl2830_platform_data;
+		struct rtl2832_platform_data rtl2832_platform_data;
+	};
 };
 
 enum rtl28xxu_chip_id {
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c
index abf8ab2e02e5..eafc5c82467f 100644
--- a/drivers/media/usb/dvb-usb/m920x.c
+++ b/drivers/media/usb/dvb-usb/m920x.c
@@ -1269,8 +1269,3 @@ MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
 MODULE_DESCRIPTION("DVB Driver for ULI M920x");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 44ae1e0661e6..49a5f9532bd8 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -820,7 +820,7 @@ static int em28xx_audio_urb_init(struct em28xx *dev)
 	if (urb_size > ep_size * npackets)
 		npackets = DIV_ROUND_UP(urb_size, ep_size);
 
-	em28xx_info("Number of URBs: %d, with %d packets and %d size",
+	em28xx_info("Number of URBs: %d, with %d packets and %d size\n",
 		    num_urb, npackets, urb_size);
 
 	/* Estimate the bytes per period */
@@ -981,7 +981,7 @@ static int em28xx_audio_fini(struct em28xx *dev)
 		return 0;
 	}
 
-	em28xx_info("Closing audio extension");
+	em28xx_info("Closing audio extension\n");
 
 	if (dev->adev.sndcard) {
 		snd_card_disconnect(dev->adev.sndcard);
@@ -1005,7 +1005,7 @@ static int em28xx_audio_suspend(struct em28xx *dev)
 	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
 		return 0;
 
-	em28xx_info("Suspending audio extension");
+	em28xx_info("Suspending audio extension\n");
 	em28xx_deinit_isoc_audio(dev);
 	atomic_set(&dev->adev.stream_started, 0);
 	return 0;
@@ -1019,7 +1019,7 @@ static int em28xx_audio_resume(struct em28xx *dev)
 	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
 		return 0;
 
-	em28xx_info("Resuming audio extension");
+	em28xx_info("Resuming audio extension\n");
 	/* Nothing to do other than schedule_work() ?? */
 	schedule_work(&dev->adev.wq_trigger);
 	return 0;
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 86461a708abe..37456079f490 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -1125,7 +1125,7 @@ int em28xx_suspend_extension(struct em28xx *dev)
 {
 	const struct em28xx_ops *ops = NULL;
 
-	em28xx_info("Suspending extensions");
+	em28xx_info("Suspending extensions\n");
 	mutex_lock(&em28xx_devlist_mutex);
 	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
 		if (ops->suspend)
@@ -1139,7 +1139,7 @@ int em28xx_resume_extension(struct em28xx *dev)
 {
 	const struct em28xx_ops *ops = NULL;
 
-	em28xx_info("Resuming extensions");
+	em28xx_info("Resuming extensions\n");
 	mutex_lock(&em28xx_devlist_mutex);
 	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
 		if (ops->resume)
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 9877b699c6bc..aee70d483264 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1724,7 +1724,7 @@ static int em28xx_dvb_fini(struct em28xx *dev)
 	if (!dev->dvb)
 		return 0;
 
-	em28xx_info("Closing DVB extension");
+	em28xx_info("Closing DVB extension\n");
 
 	dvb = dev->dvb;
 	client = dvb->i2c_client_tuner;
@@ -1775,17 +1775,17 @@ static int em28xx_dvb_suspend(struct em28xx *dev)
 	if (!dev->board.has_dvb)
 		return 0;
 
-	em28xx_info("Suspending DVB extension");
+	em28xx_info("Suspending DVB extension\n");
 	if (dev->dvb) {
 		struct em28xx_dvb *dvb = dev->dvb;
 
 		if (dvb->fe[0]) {
 			ret = dvb_frontend_suspend(dvb->fe[0]);
-			em28xx_info("fe0 suspend %d", ret);
+			em28xx_info("fe0 suspend %d\n", ret);
 		}
 		if (dvb->fe[1]) {
 			dvb_frontend_suspend(dvb->fe[1]);
-			em28xx_info("fe1 suspend %d", ret);
+			em28xx_info("fe1 suspend %d\n", ret);
 		}
 	}
 
@@ -1802,18 +1802,18 @@ static int em28xx_dvb_resume(struct em28xx *dev)
 	if (!dev->board.has_dvb)
 		return 0;
 
-	em28xx_info("Resuming DVB extension");
+	em28xx_info("Resuming DVB extension\n");
 	if (dev->dvb) {
 		struct em28xx_dvb *dvb = dev->dvb;
 
 		if (dvb->fe[0]) {
 			ret = dvb_frontend_resume(dvb->fe[0]);
-			em28xx_info("fe0 resume %d", ret);
+			em28xx_info("fe0 resume %d\n", ret);
 		}
 
 		if (dvb->fe[1]) {
 			ret = dvb_frontend_resume(dvb->fe[1]);
-			em28xx_info("fe1 resume %d", ret);
+			em28xx_info("fe1 resume %d\n", ret);
 		}
 	}
 
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index d8dc03aadfbd..4007356d991d 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -654,8 +654,6 @@ next_button:
 	if (dev->num_button_polling_addresses) {
 		memset(dev->button_polling_last_values, 0,
 		       EM28XX_NUM_BUTTON_ADDRESSES_MAX);
-		INIT_DELAYED_WORK(&dev->buttons_query_work,
-				  em28xx_query_buttons);
 		schedule_delayed_work(&dev->buttons_query_work,
 				      msecs_to_jiffies(dev->button_polling_interval));
 	}
@@ -689,6 +687,7 @@ static int em28xx_ir_init(struct em28xx *dev)
 	}
 
 	kref_get(&dev->ref);
+	INIT_DELAYED_WORK(&dev->buttons_query_work, em28xx_query_buttons);
 
 	if (dev->board.buttons)
 		em28xx_init_buttons(dev);
@@ -833,7 +832,7 @@ static int em28xx_ir_fini(struct em28xx *dev)
 		return 0;
 	}
 
-	em28xx_info("Closing input extension");
+	em28xx_info("Closing input extension\n");
 
 	em28xx_shutdown_buttons(dev);
 
@@ -862,7 +861,7 @@ static int em28xx_ir_suspend(struct em28xx *dev)
 	if (dev->is_audio_only)
 		return 0;
 
-	em28xx_info("Suspending input extension");
+	em28xx_info("Suspending input extension\n");
 	if (ir)
 		cancel_delayed_work_sync(&ir->work);
 	cancel_delayed_work_sync(&dev->buttons_query_work);
@@ -879,7 +878,7 @@ static int em28xx_ir_resume(struct em28xx *dev)
 	if (dev->is_audio_only)
 		return 0;
 
-	em28xx_info("Resuming input extension");
+	em28xx_info("Resuming input extension\n");
 	/* if suspend calls ir_raw_event_unregister(), the should call
 	   ir_raw_event_register() */
 	if (ir)
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index cf7f58b76292..9ecf65629b3d 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1958,7 +1958,7 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
 	if (v4l2 == NULL)
 		return 0;
 
-	em28xx_info("Closing video extension");
+	em28xx_info("Closing video extension\n");
 
 	mutex_lock(&dev->lock);
 
@@ -2007,7 +2007,7 @@ static int em28xx_v4l2_suspend(struct em28xx *dev)
 	if (!dev->has_video)
 		return 0;
 
-	em28xx_info("Suspending video extension");
+	em28xx_info("Suspending video extension\n");
 	em28xx_stop_urbs(dev);
 	return 0;
 }
@@ -2020,7 +2020,7 @@ static int em28xx_v4l2_resume(struct em28xx *dev)
 	if (!dev->has_video)
 		return 0;
 
-	em28xx_info("Resuming video extension");
+	em28xx_info("Resuming video extension\n");
 	/* what do we do here */
 	return 0;
 }
@@ -2192,7 +2192,6 @@ static struct video_device
 
 	*vfd		= *template;
 	vfd->v4l2_dev	= &dev->v4l2->v4l2_dev;
-	vfd->debug	= video_debug;
 	vfd->lock	= &dev->lock;
 	if (dev->board.is_webcam)
 		vfd->tvnorms = 0;
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
index eed10d782535..60af3b167f3b 100644
--- a/drivers/media/usb/gspca/Kconfig
+++ b/drivers/media/usb/gspca/Kconfig
@@ -395,6 +395,16 @@ config USB_GSPCA_TOPRO
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_topro.
 
+config USB_GSPCA_TOUPTEK
+	tristate "Touptek USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the ToupTek UCMOS
+	  / AmScope MU series camera.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_touptek.
+
 config USB_GSPCA_TV8532
 	tristate "TV8532 USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/usb/gspca/Makefile b/drivers/media/usb/gspca/Makefile
index f46975e4c82d..9f5ccecb9c8a 100644
--- a/drivers/media/usb/gspca/Makefile
+++ b/drivers/media/usb/gspca/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_GSPCA_STK1135)  += gspca_stk1135.o
 obj-$(CONFIG_USB_GSPCA_STV0680)  += gspca_stv0680.o
 obj-$(CONFIG_USB_GSPCA_T613)     += gspca_t613.o
 obj-$(CONFIG_USB_GSPCA_TOPRO)    += gspca_topro.o
+obj-$(CONFIG_USB_GSPCA_TOUPTEK)  += gspca_touptek.o
 obj-$(CONFIG_USB_GSPCA_TV8532)   += gspca_tv8532.o
 obj-$(CONFIG_USB_GSPCA_VC032X)   += gspca_vc032x.o
 obj-$(CONFIG_USB_GSPCA_VICAM)    += gspca_vicam.o
@@ -86,6 +87,7 @@ gspca_stv0680-objs  := stv0680.o
 gspca_sunplus-objs  := sunplus.o
 gspca_t613-objs     := t613.o
 gspca_topro-objs    := topro.o
+gspca_touptek-objs  := touptek.o
 gspca_tv8532-objs   := tv8532.o
 gspca_vc032x-objs   := vc032x.o
 gspca_vicam-objs    := vicam.o
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 43d65057a5fe..e54cee856a80 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -1562,7 +1562,7 @@ static int vidioc_s_parm(struct file *filp, void *priv,
 			struct v4l2_streamparm *parm)
 {
 	struct gspca_dev *gspca_dev = video_drvdata(filp);
-	int n;
+	unsigned int n;
 
 	n = parm->parm.capture.readbuffers;
 	if (n == 0 || n >= GSPCA_MAX_FRAMES)
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
index 90f0d637cd9d..a9c866d6d82d 100644
--- a/drivers/media/usb/gspca/ov534.c
+++ b/drivers/media/usb/gspca/ov534.c
@@ -12,6 +12,8 @@
  * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr
  * PS3 Eye camera - brightness, contrast, awb, agc, aec controls
  *                  added by Max Thrun <bear24rw@gmail.com>
+ * PS3 Eye camera - FPS range extended by Joseph Howse
+ *                  <josephhowse@nummist.com> http://nummist.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
@@ -116,7 +118,7 @@ static const struct v4l2_pix_format ov767x_mode[] = {
 		.colorspace = V4L2_COLORSPACE_JPEG},
 };
 
-static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
+static const u8 qvga_rates[] = {187, 150, 137, 125, 100, 75, 60, 50, 37, 30};
 static const u8 vga_rates[] = {60, 50, 40, 30, 15};
 
 static const struct framerates ov772x_framerates[] = {
@@ -769,12 +771,16 @@ static void set_frame_rate(struct gspca_dev *gspca_dev)
 		{15, 0x03, 0x41, 0x04},
 	};
 	static const struct rate_s rate_1[] = {	/* 320x240 */
+/*		{205, 0x01, 0xc1, 0x02},  * 205 FPS: video is partly corrupt */
+		{187, 0x01, 0x81, 0x02}, /* 187 FPS or below: video is valid */
+		{150, 0x01, 0xc1, 0x04},
+		{137, 0x02, 0xc1, 0x02},
 		{125, 0x02, 0x81, 0x02},
 		{100, 0x02, 0xc1, 0x04},
 		{75, 0x03, 0xc1, 0x04},
 		{60, 0x04, 0xc1, 0x04},
 		{50, 0x02, 0x41, 0x04},
-		{40, 0x03, 0x41, 0x04},
+		{37, 0x03, 0x41, 0x04},
 		{30, 0x04, 0x41, 0x04},
 	};
 
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
index 49d209bbf9ee..6ac93d8db427 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -505,13 +505,13 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
 {
 	int ret = -EINVAL;
 
-	if (len == 1 && data[0] == 0x80) {
+	if (len == 1 && (data[0] == 0x80 || data[0] == 0x10)) {
 		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
 		input_sync(gspca_dev->input_dev);
 		ret = 0;
 	}
 
-	if (len == 1 && data[0] == 0x88) {
+	if (len == 1 && (data[0] == 0x88 || data[0] == 0x11)) {
 		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
 		input_sync(gspca_dev->input_dev);
 		ret = 0;
diff --git a/drivers/media/usb/gspca/touptek.c b/drivers/media/usb/gspca/touptek.c
new file mode 100644
index 000000000000..7bac6bc96063
--- /dev/null
+++ b/drivers/media/usb/gspca/touptek.c
@@ -0,0 +1,731 @@
+/*
+ * ToupTek UCMOS / AmScope MU series camera driver
+ * TODO: contrast with ScopeTek / AmScope MDC cameras
+ *
+ * Copyright (C) 2012-2014 John McMaster <JohnDMcMaster@gmail.com>
+ *
+ * Special thanks to Bushing for helping with the decrypt algorithm and
+ * Sean O'Sullivan / the Rensselaer Center for Open Source
+ * Software (RCOS) for helping me learn kernel development
+ *
+ * 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
+ * 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.
+ */
+
+#include "gspca.h"
+
+#define MODULE_NAME "touptek"
+
+MODULE_AUTHOR("John McMaster");
+MODULE_DESCRIPTION("ToupTek UCMOS / Amscope MU microscope camera driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Exposure reg is linear with exposure time
+ * Exposure (sec), E (reg)
+ * 0.000400, 0x0002
+ * 0.001000, 0x0005
+ * 0.005000, 0x0019
+ * 0.020000, 0x0064
+ * 0.080000, 0x0190
+ * 0.400000, 0x07D0
+ * 1.000000, 0x1388
+ * 2.000000, 0x2710
+ *
+ * Three gain stages
+ * 0x1000: master channel enable bit
+ * 0x007F: low gain bits
+ * 0x0080: medium gain bit
+ * 0x0100: high gain bit
+ * gain = enable * (1 + regH) * (1 + regM) * z * regL
+ *
+ * Gain implementation
+ * Want to do something similar to mt9v011.c's set_balance
+ *
+ * Gain does not vary with resolution (checked 640x480 vs 1600x1200)
+ *
+ * Constant derivation:
+ *
+ * Raw data:
+ * Gain,   GTOP,   B,	  R,	  GBOT
+ * 1.00,   0x105C, 0x1068, 0x10C8, 0x105C
+ * 1.20,   0x106E, 0x107E, 0x10D6, 0x106E
+ * 1.40,   0x10C0, 0x10CA, 0x10E5, 0x10C0
+ * 1.60,   0x10C9, 0x10D4, 0x10F3, 0x10C9
+ * 1.80,   0x10D2, 0x10DE, 0x11C1, 0x10D2
+ * 2.00,   0x10DC, 0x10E9, 0x11C8, 0x10DC
+ * 2.20,   0x10E5, 0x10F3, 0x11CF, 0x10E5
+ * 2.40,   0x10EE, 0x10FE, 0x11D7, 0x10EE
+ * 2.60,   0x10F7, 0x11C4, 0x11DE, 0x10F7
+ * 2.80,   0x11C0, 0x11CA, 0x11E5, 0x11C0
+ * 3.00,   0x11C5, 0x11CF, 0x11ED, 0x11C5
+ *
+ * zR = 0.0069605943152454778
+ *	about 3/431 = 0.0069605568445475635
+ * zB = 0.0095695970695970703
+ *	about 6/627 = 0.0095693779904306216
+ * zG = 0.010889328063241107
+ *	about 6/551 = 0.010889292196007259
+ * about 10 bits for constant + 7 bits for value => at least 17 bit
+ * intermediate with 32 bit ints should be fine for overflow etc
+ * Essentially gains are in range 0-0x001FF
+ *
+ * However, V4L expects a main gain channel + R and B balance
+ * To keep things simple for now saturate the values of balance is too high/low
+ * This isn't really ideal but easy way to fit the Linux model
+ *
+ * Converted using gain model turns out to be quite linear:
+ * Gain, GTOP, B, R, GBOT
+ * 1.00, 92, 104, 144, 92
+ * 1.20, 110, 126, 172, 110
+ * 1.40, 128, 148, 202, 128
+ * 1.60, 146, 168, 230, 146
+ * 1.80, 164, 188, 260, 164
+ * 2.00, 184, 210, 288, 184
+ * 2.20, 202, 230, 316, 202
+ * 2.40, 220, 252, 348, 220
+ * 2.60, 238, 272, 376, 238
+ * 2.80, 256, 296, 404, 256
+ * 3.00, 276, 316, 436, 276
+ *
+ * Maximum gain is 0x7FF * 2 * 2 => 0x1FFC (8188)
+ * or about 13 effective bits of gain
+ * The highest the commercial driver goes in my setup 436
+ * However, because could *maybe* damage circuits
+ * limit the gain until have a reason to go higher
+ * Solution: gain clipped and warning emitted
+ */
+#define GAIN_MAX		511
+
+/* Frame sync is a short read */
+#define BULK_SIZE		0x4000
+
+/* MT9E001 reg names to give a rough approximation */
+#define REG_COARSE_INTEGRATION_TIME_	0x3012
+#define REG_GROUPED_PARAMETER_HOLD_	0x3022
+#define REG_MODE_SELECT			0x0100
+#define REG_OP_SYS_CLK_DIV		0x030A
+#define REG_VT_SYS_CLK_DIV		0x0302
+#define REG_PRE_PLL_CLK_DIV		0x0304
+#define REG_VT_PIX_CLK_DIV		0x0300
+#define REG_OP_PIX_CLK_DIV		0x0308
+#define REG_PLL_MULTIPLIER		0x0306
+#define REG_COARSE_INTEGRATION_TIME_	0x3012
+#define REG_FRAME_LENGTH_LINES		0x0340
+#define REG_FRAME_LENGTH_LINES_		0x300A
+#define REG_GREEN1_GAIN			0x3056
+#define REG_GREEN2_GAIN			0x305C
+#define REG_GROUPED_PARAMETER_HOLD	0x0104
+#define REG_LINE_LENGTH_PCK_		0x300C
+#define REG_MODE_SELECT			0x0100
+#define REG_PLL_MULTIPLIER		0x0306
+#define REG_READ_MODE			0x3040
+#define REG_BLUE_GAIN			0x3058
+#define REG_RED_GAIN			0x305A
+#define REG_RESET_REGISTER		0x301A
+#define REG_SCALE_M			0x0404
+#define REG_SCALING_MODE		0x0400
+#define REG_SOFTWARE_RESET		0x0103
+#define REG_X_ADDR_END			0x0348
+#define REG_X_ADDR_START		0x0344
+#define REG_X_ADDR_START		0x0344
+#define REG_X_OUTPUT_SIZE		0x034C
+#define REG_Y_ADDR_END			0x034A
+#define REG_Y_ADDR_START		0x0346
+#define REG_Y_OUTPUT_SIZE		0x034E
+
+
+/* specific webcam descriptor */
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+	/* How many bytes this frame */
+	unsigned int this_f;
+
+	/*
+	Device has separate gains for each Bayer quadrant
+	V4L supports master gain which is referenced to G1/G2 and supplies
+	individual balance controls for R/B
+	*/
+	struct v4l2_ctrl *blue;
+	struct v4l2_ctrl *red;
+};
+
+/* Used to simplify reg write error handling */
+struct cmd {
+	u16 value;
+	u16 index;
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+	{800, 600,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.bytesperline = 800,
+		.sizeimage = 800 * 600,
+		.colorspace = V4L2_COLORSPACE_SRGB},
+	{1600, 1200,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.bytesperline = 1600,
+		.sizeimage = 1600 * 1200,
+		.colorspace = V4L2_COLORSPACE_SRGB},
+	{3264, 2448,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.bytesperline = 3264,
+		.sizeimage = 3264 * 2448,
+		.colorspace = V4L2_COLORSPACE_SRGB},
+};
+
+/*
+ * As theres no known frame sync, the only way to keep synced is to try hard
+ * to never miss any packets
+ */
+#if MAX_NURBS < 4
+#error "Not enough URBs in the gspca table"
+#endif
+
+static int val_reply(struct gspca_dev *gspca_dev, const char *reply, int rc)
+{
+	if (rc < 0) {
+		PERR("reply has error %d", rc);
+		return -EIO;
+	}
+	if (rc != 1) {
+		PERR("Bad reply size %d", rc);
+		return -EIO;
+	}
+	if (reply[0] != 0x08) {
+		PERR("Bad reply 0x%02X", reply[0]);
+		return -EIO;
+	}
+	return 0;
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
+{
+	char buff[1];
+	int rc;
+
+	PDEBUG(D_USBO,
+		"reg_w bReq=0x0B, bReqT=0xC0, wVal=0x%04X, wInd=0x%04X\n",
+		value, index);
+	rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0),
+		0x0B, 0xC0, value, index, buff, 1, 500);
+	PDEBUG(D_USBO, "rc=%d, ret={0x%02X}", rc, buff[0]);
+	if (rc < 0) {
+		PERR("Failed reg_w(0x0B, 0xC0, 0x%04X, 0x%04X) w/ rc %d\n",
+			value, index, rc);
+		gspca_dev->usb_err = rc;
+		return;
+	}
+	if (val_reply(gspca_dev, buff, rc)) {
+		PERR("Bad reply to reg_w(0x0B, 0xC0, 0x%04X, 0x%04X\n",
+			value, index);
+		gspca_dev->usb_err = -EIO;
+	}
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+		const struct cmd *p, int l)
+{
+	do {
+		reg_w(gspca_dev, p->value, p->index);
+		p++;
+	} while (--l > 0);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+	u16 value;
+	unsigned int w = gspca_dev->pixfmt.width;
+
+	if (w == 800)
+		value = val * 5;
+	else if (w == 1600)
+		value = val * 3;
+	else if (w == 3264)
+		value = val * 3 / 2;
+	else {
+		PERR("Invalid width %u\n", w);
+		gspca_dev->usb_err = -EINVAL;
+		return;
+	}
+	PDEBUG(D_STREAM, "exposure: 0x%04X ms\n", value);
+	/* Wonder if theres a good reason for sending it twice */
+	/* probably not but leave it in because...why not */
+	reg_w(gspca_dev, value, REG_COARSE_INTEGRATION_TIME_);
+	reg_w(gspca_dev, value, REG_COARSE_INTEGRATION_TIME_);
+}
+
+static int gainify(int in)
+{
+	/*
+	 * TODO: check if there are any issues with corner cases
+	 * 0x000 (0):0x07F (127): regL
+	 * 0x080 (128) - 0x0FF (255): regM, regL
+	 * 0x100 (256) - max: regH, regM, regL
+	 */
+	if (in <= 0x7F)
+		return 0x1000 | in;
+	else if (in <= 0xFF)
+		return 0x1080 | in / 2;
+	else
+		return 0x1180 | in / 4;
+}
+
+static void setggain(struct gspca_dev *gspca_dev, u16 global_gain)
+{
+	u16 normalized;
+
+	normalized = gainify(global_gain);
+	PDEBUG(D_STREAM, "gain G1/G2 (0x%04X): 0x%04X (src 0x%04X)\n",
+		 REG_GREEN1_GAIN,
+		 normalized, global_gain);
+
+	reg_w(gspca_dev, normalized, REG_GREEN1_GAIN);
+	reg_w(gspca_dev, normalized, REG_GREEN2_GAIN);
+}
+
+static void setbgain(struct gspca_dev *gspca_dev,
+		u16 gain, u16 global_gain)
+{
+	u16 normalized;
+
+	normalized = global_gain +
+		((u32)global_gain) * gain / GAIN_MAX;
+	if (normalized > GAIN_MAX) {
+		PDEBUG(D_STREAM, "Truncating blue 0x%04X w/ value 0x%04X\n",
+			 GAIN_MAX, normalized);
+		normalized = GAIN_MAX;
+	}
+	normalized = gainify(normalized);
+	PDEBUG(D_STREAM, "gain B (0x%04X): 0x%04X w/ source 0x%04X\n",
+		 REG_BLUE_GAIN, normalized, gain);
+
+	reg_w(gspca_dev, normalized, REG_BLUE_GAIN);
+}
+
+static void setrgain(struct gspca_dev *gspca_dev,
+		u16 gain, u16 global_gain)
+{
+	u16 normalized;
+
+	normalized = global_gain +
+		((u32)global_gain) * gain / GAIN_MAX;
+	if (normalized > GAIN_MAX) {
+		PDEBUG(D_STREAM, "Truncating gain 0x%04X w/ value 0x%04X\n",
+			 GAIN_MAX, normalized);
+		normalized = GAIN_MAX;
+	}
+	normalized = gainify(normalized);
+	PDEBUG(D_STREAM, "gain R (0x%04X): 0x%04X w / source 0x%04X\n",
+		 REG_RED_GAIN, normalized, gain);
+
+	reg_w(gspca_dev, normalized, REG_RED_GAIN);
+}
+
+static void configure_wh(struct gspca_dev *gspca_dev)
+{
+	unsigned int w = gspca_dev->pixfmt.width;
+
+	PDEBUG(D_STREAM, "configure_wh\n");
+
+	if (w == 800) {
+		static const struct cmd reg_init_res[] = {
+			{0x0060, REG_X_ADDR_START},
+			{0x0CD9, REG_X_ADDR_END},
+			{0x0036, REG_Y_ADDR_START},
+			{0x098F, REG_Y_ADDR_END},
+			{0x07C7, REG_READ_MODE},
+		};
+
+		reg_w_buf(gspca_dev,
+			       reg_init_res, ARRAY_SIZE(reg_init_res));
+	} else if (w == 1600) {
+		static const struct cmd reg_init_res[] = {
+			{0x009C, REG_X_ADDR_START},
+			{0x0D19, REG_X_ADDR_END},
+			{0x0068, REG_Y_ADDR_START},
+			{0x09C5, REG_Y_ADDR_END},
+			{0x06C3, REG_READ_MODE},
+		};
+
+		reg_w_buf(gspca_dev,
+			       reg_init_res, ARRAY_SIZE(reg_init_res));
+	} else if (w == 3264) {
+		static const struct cmd reg_init_res[] = {
+			{0x00E8, REG_X_ADDR_START},
+			{0x0DA7, REG_X_ADDR_END},
+			{0x009E, REG_Y_ADDR_START},
+			{0x0A2D, REG_Y_ADDR_END},
+			{0x0241, REG_READ_MODE},
+		};
+
+		reg_w_buf(gspca_dev,
+			       reg_init_res, ARRAY_SIZE(reg_init_res));
+	} else {
+		PERR("bad width %u\n", w);
+		gspca_dev->usb_err = -EINVAL;
+		return;
+	}
+
+	reg_w(gspca_dev, 0x0000, REG_SCALING_MODE);
+	reg_w(gspca_dev, 0x0010, REG_SCALE_M);
+	reg_w(gspca_dev, w, REG_X_OUTPUT_SIZE);
+	reg_w(gspca_dev, gspca_dev->pixfmt.height, REG_Y_OUTPUT_SIZE);
+
+	if (w == 800) {
+		reg_w(gspca_dev, 0x0384, REG_FRAME_LENGTH_LINES_);
+		reg_w(gspca_dev, 0x0960, REG_LINE_LENGTH_PCK_);
+	} else if (w == 1600) {
+		reg_w(gspca_dev, 0x0640, REG_FRAME_LENGTH_LINES_);
+		reg_w(gspca_dev, 0x0FA0, REG_LINE_LENGTH_PCK_);
+	} else if (w == 3264) {
+		reg_w(gspca_dev, 0x0B4B, REG_FRAME_LENGTH_LINES_);
+		reg_w(gspca_dev, 0x1F40, REG_LINE_LENGTH_PCK_);
+	} else {
+		PERR("bad width %u\n", w);
+		gspca_dev->usb_err = -EINVAL;
+		return;
+	}
+}
+
+/* Packets that were encrypted, no idea if the grouping is significant */
+static void configure_encrypted(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init_begin[] = {
+		{0x0100, REG_SOFTWARE_RESET},
+		{0x0000, REG_MODE_SELECT},
+		{0x0100, REG_GROUPED_PARAMETER_HOLD},
+		{0x0004, REG_VT_PIX_CLK_DIV},
+		{0x0001, REG_VT_SYS_CLK_DIV},
+		{0x0008, REG_OP_PIX_CLK_DIV},
+		{0x0001, REG_OP_SYS_CLK_DIV},
+		{0x0004, REG_PRE_PLL_CLK_DIV},
+		{0x0040, REG_PLL_MULTIPLIER},
+		{0x0000, REG_GROUPED_PARAMETER_HOLD},
+		{0x0100, REG_GROUPED_PARAMETER_HOLD},
+	};
+	static const struct cmd reg_init_end[] = {
+		{0x0000, REG_GROUPED_PARAMETER_HOLD},
+		{0x0301, 0x31AE},
+		{0x0805, 0x3064},
+		{0x0071, 0x3170},
+		{0x10DE, REG_RESET_REGISTER},
+		{0x0000, REG_MODE_SELECT},
+		{0x0010, REG_PLL_MULTIPLIER},
+		{0x0100, REG_MODE_SELECT},
+	};
+
+	PDEBUG(D_STREAM, "Encrypted begin, w = %u\n", gspca_dev->pixfmt.width);
+	reg_w_buf(gspca_dev, reg_init_begin, ARRAY_SIZE(reg_init_begin));
+	configure_wh(gspca_dev);
+	reg_w_buf(gspca_dev, reg_init_end, ARRAY_SIZE(reg_init_end));
+	reg_w(gspca_dev, 0x0100, REG_GROUPED_PARAMETER_HOLD);
+	reg_w(gspca_dev, 0x0000, REG_GROUPED_PARAMETER_HOLD);
+
+	PDEBUG(D_STREAM, "Encrypted end\n");
+}
+
+static int configure(struct gspca_dev *gspca_dev)
+{
+	int rc;
+	uint8_t buff[4];
+
+	PDEBUG(D_STREAM, "configure()\n");
+
+	/*
+	 * First driver sets a sort of encryption key
+	 * A number of futur requests of this type have wValue and wIndex
+	 * encrypted as follows:
+	 * -Compute key = this wValue rotate left by 4 bits
+	 *	(decrypt.py rotates right because we are decrypting)
+	 * -Later packets encrypt packets by XOR'ing with key
+	 *	XOR encrypt/decrypt is symmetrical
+	 *	wValue, and wIndex are encrypted
+	 *	bRequest is not and bRequestType is always 0xC0
+	 *		This allows resyncing if key is unknown?
+	 * By setting 0 we XOR with 0 and the shifting and XOR drops out
+	 */
+	rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0),
+			     0x16, 0xC0, 0x0000, 0x0000, buff, 2, 500);
+	if (val_reply(gspca_dev, buff, rc)) {
+		PERR("failed key req");
+		return -EIO;
+	}
+
+	/*
+	 * Next does some sort of 2 packet challenge / response
+	 * evidence suggests its an Atmel I2C crypto part but nobody cares to
+	 * look
+	 * (to make sure its not cloned hardware?)
+	 * Ignore: I want to work with their hardware, not clone it
+	 * 16 bytes out challenge, requestType: 0x40
+	 * 16 bytes in response, requestType: 0xC0
+	 */
+
+	rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
+			     0x01, 0x40, 0x0001, 0x000F, NULL, 0, 500);
+	if (rc < 0) {
+		PERR("failed to replay packet 176 w/ rc %d\n", rc);
+		return rc;
+	}
+
+	rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
+			     0x01, 0x40, 0x0000, 0x000F, NULL, 0, 500);
+	if (rc < 0) {
+		PERR("failed to replay packet 178 w/ rc %d\n", rc);
+		return rc;
+	}
+
+	rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
+			     0x01, 0x40, 0x0001, 0x000F, NULL, 0, 500);
+	if (rc < 0) {
+		PERR("failed to replay packet 180 w/ rc %d\n", rc);
+		return rc;
+	}
+
+	/*
+	 * Serial number?  Doesn't seem to be required
+	 * cam1: \xE6\x0D\x00\x00, cam2: \x70\x19\x00\x00
+	 * rc = usb_control_msg(gspca_dev->dev,
+	 *			usb_rcvctrlpipe(gspca_dev->dev, 0),
+	 *			0x20, 0xC0, 0x0000, 0x0000, buff, 4, 500);
+	 */
+
+	/* Large (EEPROM?) read, skip it since no idea what to do with it */
+	gspca_dev->usb_err = 0;
+	configure_encrypted(gspca_dev);
+	if (gspca_dev->usb_err)
+		return gspca_dev->usb_err;
+
+	/* Omitted this by accident, does not work without it */
+	rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
+			     0x01, 0x40, 0x0003, 0x000F, NULL, 0, 500);
+	if (rc < 0) {
+		PERR("failed to replay final packet w/ rc %d\n", rc);
+		return rc;
+	}
+
+	PDEBUG(D_STREAM, "Configure complete\n");
+	return 0;
+}
+
+static int sd_config(struct gspca_dev *gspca_dev,
+		     const struct usb_device_id *id)
+{
+	gspca_dev->cam.cam_mode = vga_mode;
+	gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+
+	/* Yes we want URBs and we want them now! */
+	gspca_dev->cam.no_urb_create = 0;
+	gspca_dev->cam.bulk_nurbs = 4;
+	/* Largest size the windows driver uses */
+	gspca_dev->cam.bulk_size = BULK_SIZE;
+	/* Def need to use bulk transfers */
+	gspca_dev->cam.bulk = 1;
+
+	return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int rc;
+
+	sd->this_f = 0;
+
+	rc = configure(gspca_dev);
+	if (rc < 0) {
+		PERR("Failed configure");
+		return rc;
+	}
+	/* First two frames have messed up gains
+	Drop them to avoid special cases in user apps? */
+	return 0;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			u8 *data,	/* isoc packet */
+			int len)	/* iso packet length */
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (len != BULK_SIZE) {
+		/* can we finish a frame? */
+		if (sd->this_f + len == gspca_dev->pixfmt.sizeimage) {
+			gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
+			PDEBUG(D_FRAM, "finish frame sz %u/%u w/ len %u\n",
+				 sd->this_f, gspca_dev->pixfmt.sizeimage, len);
+		/* lost some data, discard the frame */
+		} else {
+			gspca_frame_add(gspca_dev, DISCARD_PACKET, NULL, 0);
+			PDEBUG(D_FRAM, "abort frame sz %u/%u w/ len %u\n",
+				 sd->this_f, gspca_dev->pixfmt.sizeimage, len);
+		}
+		sd->this_f = 0;
+	} else {
+		if (sd->this_f == 0)
+			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+		else
+			gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+		sd->this_f += len;
+	}
+}
+
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	return 0;
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	gspca_dev->usb_err = 0;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		setexposure(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_GAIN:
+		/* gspca_dev->gain automatically updated */
+		setggain(gspca_dev, gspca_dev->gain->val);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		sd->blue->val = ctrl->val;
+		setbgain(gspca_dev, sd->blue->val, gspca_dev->gain->val);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		sd->red->val = ctrl->val;
+		setrgain(gspca_dev, sd->red->val, gspca_dev->gain->val);
+		break;
+	}
+	return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+	.s_ctrl = sd_s_ctrl,
+};
+
+static int sd_init_controls(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+	gspca_dev->vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+
+	gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+	/* Mostly limited by URB timeouts */
+	/* XXX: make dynamic based on frame rate? */
+		V4L2_CID_EXPOSURE, 0, 800, 1, 350);
+	gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_GAIN, 0, 511, 1, 128);
+	sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_BLUE_BALANCE, 0, 1023, 1, 80);
+	sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_RED_BALANCE, 0, 1023, 1, 295);
+
+	if (hdl->error) {
+		PERR("Could not initialize controls\n");
+		return hdl->error;
+	}
+	return 0;
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+	.name = MODULE_NAME,
+	.config = sd_config,
+	.init = sd_init,
+	.init_controls = sd_init_controls,
+	.start = sd_start,
+	.pkt_scan = sd_pkt_scan,
+};
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+	/* Commented out devices should be related */
+	/* AS: AmScope, TT: ToupTek */
+	/* { USB_DEVICE(0x0547, 0x6035) },  TT UCMOS00350KPA */
+	/* { USB_DEVICE(0x0547, 0x6130) },  TT UCMOS01300KPA */
+	/* { USB_DEVICE(0x0547, 0x6200) },  TT UCMOS02000KPA */
+	/* { USB_DEVICE(0x0547, 0x6310) },  TT UCMOS03100KPA */
+	/* { USB_DEVICE(0x0547, 0x6510) },  TT UCMOS05100KPA */
+	/* { USB_DEVICE(0x0547, 0x6800) },  TT UCMOS08000KPA */
+	/* { USB_DEVICE(0x0547, 0x6801) },  TT UCMOS08000KPB */
+	{ USB_DEVICE(0x0547, 0x6801) }, /* TT UCMOS08000KPB, AS MU800 */
+	/* { USB_DEVICE(0x0547, 0x6900) },  TT UCMOS09000KPA */
+	/* { USB_DEVICE(0x0547, 0x6901) },  TT UCMOS09000KPB */
+	/* { USB_DEVICE(0x0547, 0x6010) },  TT UCMOS10000KPA */
+	/* { USB_DEVICE(0x0547, 0x6014) },  TT UCMOS14000KPA */
+	/* { USB_DEVICE(0x0547, 0x6131) },  TT UCMOS01300KMA */
+	/* { USB_DEVICE(0x0547, 0x6511) },  TT UCMOS05100KMA */
+	/* { USB_DEVICE(0x0547, 0x8080) },  TT UHCCD00800KPA */
+	/* { USB_DEVICE(0x0547, 0x8140) },  TT UHCCD01400KPA */
+	/* { USB_DEVICE(0x0547, 0x8141) },  TT EXCCD01400KPA */
+	/* { USB_DEVICE(0x0547, 0x8200) },  TT UHCCD02000KPA */
+	/* { USB_DEVICE(0x0547, 0x8201) },  TT UHCCD02000KPB */
+	/* { USB_DEVICE(0x0547, 0x8310) },  TT UHCCD03100KPA */
+	/* { USB_DEVICE(0x0547, 0x8500) },  TT UHCCD05000KPA */
+	/* { USB_DEVICE(0x0547, 0x8510) },  TT UHCCD05100KPA */
+	/* { USB_DEVICE(0x0547, 0x8600) },  TT UHCCD06000KPA */
+	/* { USB_DEVICE(0x0547, 0x8800) },  TT UHCCD08000KPA */
+	/* { USB_DEVICE(0x0547, 0x8315) },  TT UHCCD03150KPA */
+	/* { USB_DEVICE(0x0547, 0x7800) },  TT UHCCD00800KMA */
+	/* { USB_DEVICE(0x0547, 0x7140) },  TT UHCCD01400KMA */
+	/* { USB_DEVICE(0x0547, 0x7141) },  TT UHCCD01400KMB */
+	/* { USB_DEVICE(0x0547, 0x7200) },  TT UHCCD02000KMA */
+	/* { USB_DEVICE(0x0547, 0x7315) },  TT UHCCD03150KMA */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static int sd_probe(struct usb_interface *intf,
+		    const struct usb_device_id *id)
+{
+	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+			     THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+	.name = MODULE_NAME,
+	.id_table = device_table,
+	.probe = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume = gspca_resume,
+#endif
+};
+
+static int __init sd_mod_init(void)
+{
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c
index c00ac57de510..b4efb2fb36fa 100644
--- a/drivers/media/usb/gspca/vc032x.c
+++ b/drivers/media/usb/gspca/vc032x.c
@@ -68,12 +68,12 @@ enum sensors {
 
 static const struct v4l2_pix_format vc0321_mode[] = {
 	{320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
-		.bytesperline = 320,
+		.bytesperline = 320 * 2,
 		.sizeimage = 320 * 240 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 1},
 	{640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
-		.bytesperline = 640,
+		.bytesperline = 640 * 2,
 		.sizeimage = 640 * 480 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 0},
@@ -97,17 +97,17 @@ static const struct v4l2_pix_format vc0323_mode[] = {
 };
 static const struct v4l2_pix_format bi_mode[] = {
 	{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-		.bytesperline = 320,
+		.bytesperline = 320 * 2,
 		.sizeimage = 320 * 240 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 2},
 	{640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-		.bytesperline = 640,
+		.bytesperline = 640 * 2,
 		.sizeimage = 640 * 480 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 1},
 	{1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-		.bytesperline = 1280,
+		.bytesperline = 1280 * 2,
 		.sizeimage = 1280 * 1024 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 0},
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-audio.c b/drivers/media/usb/pvrusb2/pvrusb2-audio.c
index cc06d5e4adcc..45276c628482 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-audio.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.c
@@ -84,13 +84,3 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 			MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
 	}
 }
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-audio.h b/drivers/media/usb/pvrusb2/pvrusb2-audio.h
index e3e63d750891..27cefb5cb170 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-audio.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.h
@@ -25,13 +25,3 @@
 #include "pvrusb2-hdw-internal.h"
 void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
 #endif /* __PVRUSB2_AUDIO_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c
index c8761c71c9d2..924fc4c6019a 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c
@@ -418,14 +418,3 @@ struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
 	pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
 	return cp;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.h b/drivers/media/usb/pvrusb2/pvrusb2-context.h
index d657e53bbfa3..1c1d442d9ea3 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-context.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-context.h
@@ -83,12 +83,3 @@ int pvr2_context_global_init(void);
 void pvr2_context_global_done(void);
 
 #endif /* __PVRUSB2_CONTEXT_H */
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c
index 88320900dbd4..f82f0f0f2c04 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c
@@ -82,14 +82,3 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 		sd->ops->audio->s_routing(sd, input, 0, 0);
 	}
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h
index 53ba548b72a7..86c17bee56f9 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h
@@ -36,13 +36,3 @@
 void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
 
 #endif /* __PVRUSB2_AUDIO_CS53L32A_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c
index 7d5a7139a45a..958db170a048 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c
@@ -596,14 +596,3 @@ int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
 	return ret;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h
index 794ff90121c7..c175571868a3 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h
@@ -110,13 +110,3 @@ int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
 			   unsigned int *len);
 
 #endif /* __PVRUSB2_CTRL_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c
index c514d0b9ffdc..1a81aa70509b 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -152,15 +152,3 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 		sd->ops->audio->s_routing(sd, (u32)aud_input, 0, 0);
 	}
 }
-
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h
index e35c2322a08c..2eed7b7ee25e 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h
@@ -40,13 +40,3 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd);
 
 
 #endif /* __PVRUSB2_CX2584X_V4L_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debug.h b/drivers/media/usb/pvrusb2/pvrusb2-debug.h
index be79249f8628..4ef2ebcd97a5 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-debug.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-debug.h
@@ -57,13 +57,3 @@ extern int pvrusb2_debug;
 
 
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c
index 4279ebb811a1..e4022bcb155b 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c
@@ -322,14 +322,3 @@ int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
 
 	return 0;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h
index 2f8d46761cd0..a8dfc55f136f 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h
@@ -40,13 +40,3 @@ int pvr2_debugifc_docmd(struct pvr2_hdw *,
 			const char *buf_ptr,unsigned int buf_size);
 
 #endif /* __PVRUSB2_DEBUGIFC_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-devattr.c b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c
index adc501d3c287..06c4c3dabcde 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c
@@ -564,13 +564,3 @@ MODULE_FIRMWARE(PVR2_FIRMWARE_29xxx);
 MODULE_FIRMWARE(PVR2_FIRMWARE_24xxx);
 MODULE_FIRMWARE(PVR2_FIRMWARE_73xxx);
 MODULE_FIRMWARE(PVR2_FIRMWARE_75xxx);
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-devattr.h b/drivers/media/usb/pvrusb2/pvrusb2-devattr.h
index 273c8d4b3853..5aeefb6a991f 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-devattr.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.h
@@ -187,13 +187,3 @@ struct pvr2_device_desc {
 extern struct usb_device_id pvr2_device_table[];
 
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
index 9515f3a68f8f..e1907cd0c3b7 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
@@ -152,13 +152,3 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
 
 	return 0;
 }
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h
index cca3216f94cc..f1e33c807f46 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h
@@ -27,13 +27,3 @@ struct pvr2_hdw;
 int pvr2_eeprom_analyze(struct pvr2_hdw *);
 
 #endif /* __PVRUSB2_EEPROM_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c
index f7702aeeda3f..593b3e9b6bfd 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c
@@ -538,14 +538,3 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
 
 	return status;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-encoder.h b/drivers/media/usb/pvrusb2/pvrusb2-encoder.h
index 232fefbcd1ac..a2bfb48f1ecd 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-encoder.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.h
@@ -30,13 +30,3 @@ int pvr2_encoder_start(struct pvr2_hdw *);
 int pvr2_encoder_stop(struct pvr2_hdw *);
 
 #endif /* __PVRUSB2_ENCODER_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h
index 614755ea2ea3..06a15a68bcfd 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h
@@ -60,13 +60,3 @@
 #define FX2CMD_ONAIR_DTV_POWER_OFF     0xa3u
 
 #endif /* _PVRUSB2_FX2_CMD_H_ */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h
index 036952f2a3cb..1f9c02801cee 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h
@@ -394,13 +394,3 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *);
 void pvr2_hdw_status_poll(struct pvr2_hdw *);
 
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index 2fd9b5e0e2a9..930593d7028d 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -2425,22 +2425,18 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 	}
 	if (!hdw) goto fail;
 
-	init_timer(&hdw->quiescent_timer);
-	hdw->quiescent_timer.data = (unsigned long)hdw;
-	hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout;
+	setup_timer(&hdw->quiescent_timer, pvr2_hdw_quiescent_timeout,
+		    (unsigned long)hdw);
 
-	init_timer(&hdw->decoder_stabilization_timer);
-	hdw->decoder_stabilization_timer.data = (unsigned long)hdw;
-	hdw->decoder_stabilization_timer.function =
-		pvr2_hdw_decoder_stabilization_timeout;
+	setup_timer(&hdw->decoder_stabilization_timer,
+		    pvr2_hdw_decoder_stabilization_timeout,
+		    (unsigned long)hdw);
 
-	init_timer(&hdw->encoder_wait_timer);
-	hdw->encoder_wait_timer.data = (unsigned long)hdw;
-	hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
+	setup_timer(&hdw->encoder_wait_timer, pvr2_hdw_encoder_wait_timeout,
+		    (unsigned long)hdw);
 
-	init_timer(&hdw->encoder_run_timer);
-	hdw->encoder_run_timer.data = (unsigned long)hdw;
-	hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
+	setup_timer(&hdw->encoder_run_timer, pvr2_hdw_encoder_run_timeout,
+		    (unsigned long)hdw);
 
 	hdw->master_state = PVR2_STATE_DEAD;
 
@@ -3680,10 +3676,8 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
 	hdw->ctl_timeout_flag = 0;
 	hdw->ctl_write_pend_flag = 0;
 	hdw->ctl_read_pend_flag = 0;
-	init_timer(&timer);
+	setup_timer(&timer, pvr2_ctl_timeout, (unsigned long)hdw);
 	timer.expires = jiffies + timeout;
-	timer.data = (unsigned long)hdw;
-	timer.function = pvr2_ctl_timeout;
 
 	if (write_len) {
 		hdw->cmd_debug_state = 2;
@@ -4035,11 +4029,6 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
 }
 
 
-int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
-{
-	return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF);
-}
-
 
 int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
 {
@@ -4301,9 +4290,8 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
 				   the encoder. */
 				if (!hdw->state_encoder_waitok) {
 					hdw->encoder_wait_timer.expires =
-						jiffies +
-						(HZ * TIME_MSEC_ENCODER_WAIT
-						 / 1000);
+						jiffies + msecs_to_jiffies(
+						TIME_MSEC_ENCODER_WAIT);
 					add_timer(&hdw->encoder_wait_timer);
 				}
 			}
@@ -4426,8 +4414,8 @@ static int state_eval_encoder_run(struct pvr2_hdw *hdw)
 		if (pvr2_encoder_start(hdw) < 0) return !0;
 		hdw->state_encoder_run = !0;
 		if (!hdw->state_encoder_runok) {
-			hdw->encoder_run_timer.expires =
-				jiffies + (HZ * TIME_MSEC_ENCODER_OK / 1000);
+			hdw->encoder_run_timer.expires = jiffies +
+				 msecs_to_jiffies(TIME_MSEC_ENCODER_OK);
 			add_timer(&hdw->encoder_run_timer);
 		}
 	}
@@ -4518,9 +4506,8 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 				   but before we did the pending check. */
 				if (!hdw->state_decoder_quiescent) {
 					hdw->quiescent_timer.expires =
-						jiffies +
-						(HZ * TIME_MSEC_DECODER_WAIT
-						 / 1000);
+						jiffies + msecs_to_jiffies(
+						TIME_MSEC_DECODER_WAIT);
 					add_timer(&hdw->quiescent_timer);
 				}
 			}
@@ -4544,9 +4531,8 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 		hdw->state_decoder_run = !0;
 		if (hdw->decoder_client_id == PVR2_CLIENT_ID_SAA7115) {
 			hdw->decoder_stabilization_timer.expires =
-				jiffies +
-				(HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT /
-				 1000);
+				jiffies + msecs_to_jiffies(
+				TIME_MSEC_DECODER_STABILIZATION_WAIT);
 			add_timer(&hdw->decoder_stabilization_timer);
 		} else {
 			hdw->state_decoder_ready = !0;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
index 41847076f51a..a82a00dd7329 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
@@ -271,9 +271,6 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
 /* Execute simple reset command */
 int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
 
-/* suspend */
-int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *);
-
 /* Order decoder to reset */
 int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
 
@@ -343,13 +340,3 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
 int pvr2_upload_firmware2(struct pvr2_hdw *hdw);
 
 #endif /* __PVRUSB2_HDW_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
index b5e929f1bf82..4baa9d632a4e 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
@@ -686,13 +686,3 @@ void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
 		hdw->i2c_linked = 0;
 	}
 }
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h
index 6a75769200bd..a10a3e8e9345 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h
@@ -27,14 +27,3 @@ void pvr2_i2c_core_done(struct pvr2_hdw *);
 
 
 #endif /* __PVRUSB2_I2C_ADAPTER_H */
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c
index 1e354747de3f..0c08f22bdfce 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c
@@ -682,14 +682,3 @@ int pvr2_buffer_get_id(struct pvr2_buffer *bp)
 {
 	return bp->id;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.h b/drivers/media/usb/pvrusb2/pvrusb2-io.h
index afb7e87c0394..0c47c6a95ab2 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-io.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-io.h
@@ -90,13 +90,3 @@ int pvr2_buffer_get_id(struct pvr2_buffer *);
 int pvr2_buffer_queue(struct pvr2_buffer *);
 
 #endif /* __PVRUSB2_IO_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ioread.c b/drivers/media/usb/pvrusb2/pvrusb2-ioread.c
index bba6115c9ae8..cd995b54732e 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-ioread.c
@@ -499,14 +499,3 @@ int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
 		   cp,req_cnt,ret);
 	return ret;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ioread.h b/drivers/media/usb/pvrusb2/pvrusb2-ioread.h
index 100e0780e1aa..0b1f0fbc3438 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-ioread.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-ioread.h
@@ -36,13 +36,3 @@ int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt);
 int pvr2_ioread_avail(struct pvr2_ioread *);
 
 #endif /* __PVRUSB2_IOREAD_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-main.c b/drivers/media/usb/pvrusb2/pvrusb2-main.c
index c1d9bb61cd77..86be902a0049 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-main.c
@@ -169,14 +169,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.9.1");
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-std.c b/drivers/media/usb/pvrusb2/pvrusb2-std.c
index 453627b07833..9a596a3a4c27 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-std.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-std.c
@@ -398,14 +398,3 @@ v4l2_std_id pvr2_std_get_usable(void)
 {
 	return CSTD_ALL;
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-std.h b/drivers/media/usb/pvrusb2/pvrusb2-std.h
index a35c53d0b320..ed4ec0474429 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-std.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-std.h
@@ -47,13 +47,3 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
 v4l2_std_id pvr2_std_get_usable(void);
 
 #endif /* __PVRUSB2_STD_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c
index 6ef1335b2858..06fe63ced58c 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c
@@ -848,14 +848,3 @@ static ssize_t debugcmd_store(struct device *class_dev,
 	return count;
 }
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h
index 6d875bfe7991..6f0579e1e07b 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h
@@ -34,13 +34,3 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *,
 				     struct pvr2_sysfs_class *);
 
 #endif /* __PVRUSB2_SYSFS_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-util.h b/drivers/media/usb/pvrusb2/pvrusb2-util.h
index 92b75544ee2e..5465bf9cd73e 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-util.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-util.h
@@ -50,13 +50,3 @@
 
 
 #endif /* __PVRUSB2_UTIL_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index 536210b39428..35e4ea530494 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -1362,13 +1362,3 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
 	pvr2_v4l2_destroy_no_lock(vp);
 	return NULL;
 }
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h
index 34c011a7b107..e455c9515841 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h
@@ -27,13 +27,3 @@ struct pvr2_v4l2;
 struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *);
 
 #endif /* __PVRUSB2_V4L2_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c
index 2e205c99eb96..139b39740534 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c
@@ -101,14 +101,3 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 		sd->ops->video->s_routing(sd, input, 0, 0);
 	}
 }
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h
index 3b0bd5db602b..dacf3ec7f9e1 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h
@@ -36,13 +36,3 @@
 void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
 
 #endif /* __PVRUSB2_VIDEO_V4L_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c
index 3ac8d751a5c0..f1df94a2436f 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c
@@ -56,15 +56,3 @@ void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 		sd->ops->audio->s_routing(sd, input, 0, 0);
 	}
 }
-
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h
index 0577bc7246fb..a4ee12e28d5c 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h
@@ -40,13 +40,3 @@ void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd);
 
 
 #endif /* __PVRUSB2_WM8775_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2.h b/drivers/media/usb/pvrusb2/pvrusb2.h
index 240de9b35661..95f98a87abb3 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2.h
@@ -30,13 +30,3 @@
 #define PVR_NUM 20
 
 #endif /* __PVRUSB2_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 15b754da4a2c..702267e208ba 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -508,7 +508,8 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
 }
 
 /* Must be called with vb_queue_lock hold */
-static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
+static void pwc_cleanup_queued_bufs(struct pwc_device *pdev,
+				    enum vb2_buffer_state state)
 {
 	unsigned long flags = 0;
 
@@ -519,7 +520,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
 		buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
 				 list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb, state);
 	}
 	spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
 }
@@ -674,7 +675,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
 		pwc_set_leds(pdev, 0, 0);
 		pwc_camera_power(pdev, 0);
 		/* And cleanup any queued bufs!! */
-		pwc_cleanup_queued_bufs(pdev);
+		pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_QUEUED);
 	}
 	mutex_unlock(&pdev->v4l2_lock);
 
@@ -692,7 +693,9 @@ static void stop_streaming(struct vb2_queue *vq)
 		pwc_isoc_cleanup(pdev);
 	}
 
-	pwc_cleanup_queued_bufs(pdev);
+	pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_ERROR);
+	if (pdev->fill_buf)
+		vb2_buffer_done(&pdev->fill_buf->vb, VB2_BUF_STATE_ERROR);
 	mutex_unlock(&pdev->v4l2_lock);
 }
 
@@ -1125,7 +1128,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
 	if (pdev->vb_queue.streaming)
 		pwc_isoc_cleanup(pdev);
 	pdev->udev = NULL;
-	pwc_cleanup_queued_bufs(pdev);
 
 	v4l2_device_disconnect(&pdev->v4l2_dev);
 	video_unregister_device(&pdev->vdev);
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index de55e96fed15..0f3c34d47ec3 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -2274,9 +2274,7 @@ static int s2255_probe(struct usb_interface *interface,
 		dev_err(&interface->dev, "Could not find bulk-in endpoint\n");
 		goto errorEP;
 	}
-	init_timer(&dev->timer);
-	dev->timer.function = s2255_timer;
-	dev->timer.data = (unsigned long)dev->fw_data;
+	setup_timer(&dev->timer, s2255_timer, (unsigned long)dev->fw_data);
 	init_waitqueue_head(&dev->fw_data->wait_fw);
 	for (i = 0; i < MAX_CHANNELS; i++) {
 		struct s2255_vc *vc = &dev->vc[i];
diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig
index 5afbd9a4b55c..d37b742d4f7a 100644
--- a/drivers/media/usb/siano/Kconfig
+++ b/drivers/media/usb/siano/Kconfig
@@ -5,7 +5,9 @@
 config SMS_USB_DRV
 	tristate "Siano SMS1xxx based MDTV receiver"
 	depends on DVB_CORE && HAS_DMA
+	depends on !RC_CORE || RC_CORE
 	select MEDIA_COMMON_OPTIONS
+	select SMS_SIANO_MDTV
 	---help---
 	  Choose if you would like to have Siano's support for USB interface
 
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index a47629108c1b..65a326c5128f 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -38,10 +38,6 @@
 #include "stk1160.h"
 #include "stk1160-reg.h"
 
-static unsigned int vidioc_debug;
-module_param(vidioc_debug, int, 0644);
-MODULE_PARM_DESC(vidioc_debug, "enable debug messages [vidioc]");
-
 static bool keep_buffers;
 module_param(keep_buffers, bool, 0644);
 MODULE_PARM_DESC(keep_buffers, "don't release buffers upon stop streaming");
@@ -659,7 +655,6 @@ int stk1160_video_register(struct stk1160 *dev)
 
 	/* Initialize video_device with a template structure */
 	dev->vdev = v4l_template;
-	dev->vdev.debug = vidioc_debug;
 	dev->vdev.queue = &dev->vb_vidq;
 
 	/*
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index 3588dc38db87..e08fa587332f 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -1262,7 +1262,6 @@ static int stk_register_video_device(struct stk_camera *dev)
 
 	dev->vdev = stk_v4l_data;
 	dev->vdev.lock = &dev->lock;
-	dev->vdev.debug = debug;
 	dev->vdev.v4l2_dev = &dev->v4l2_dev;
 	video_set_drvdata(&dev->vdev, dev);
 	err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index 793577fc4633..0f14d3ccc7b4 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -941,7 +941,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 	if (NULL == fmt) {
-		dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)"
+		dprintk(dev, 2, "Fourcc format (0x%08x)"
 				" invalid.\n", f->fmt.pix.pixelformat);
 		return -EINVAL;
 	}
@@ -1622,7 +1622,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
 	*vfd = *template;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->release = video_device_release;
-	vfd->debug = tm6000_debug;
 	vfd->lock = &dev->lock;
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c
index 302aa07c458f..44b0c28d69b6 100644
--- a/drivers/media/usb/usbvision/usbvision-core.c
+++ b/drivers/media/usb/usbvision/usbvision-core.c
@@ -2194,9 +2194,8 @@ static void usbvision_power_off_timer(unsigned long data)
 
 void usbvision_init_power_off_timer(struct usb_usbvision *usbvision)
 {
-	init_timer(&usbvision->power_off_timer);
-	usbvision->power_off_timer.data = (long)usbvision;
-	usbvision->power_off_timer.function = usbvision_power_off_timer;
+	setup_timer(&usbvision->power_off_timer, usbvision_power_off_timer,
+		    (unsigned long)usbvision);
 }
 
 void usbvision_set_power_off_timer(struct usb_usbvision *usbvision)
@@ -2502,11 +2501,3 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
 	usbvision_set_audio(usbvision, audio[channel]);
 	return 0;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/usbvision/usbvision-i2c.c b/drivers/media/usb/usbvision/usbvision-i2c.c
index ba262a32bd3a..26dbcb1146af 100644
--- a/drivers/media/usb/usbvision/usbvision-i2c.c
+++ b/drivers/media/usb/usbvision/usbvision-i2c.c
@@ -445,11 +445,3 @@ static struct i2c_adapter i2c_adap_template = {
 	.owner = THIS_MODULE,
 	.name              = "usbvision",
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index 693d5f409138..cd2fbf11e3b4 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -1716,11 +1716,3 @@ static void __exit usbvision_exit(void)
 
 module_init(usbvision_init);
 module_exit(usbvision_exit);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h
index a0c73cf1517c..77aeb1ed9a81 100644
--- a/drivers/media/usb/usbvision/usbvision.h
+++ b/drivers/media/usb/usbvision/usbvision.h
@@ -517,11 +517,3 @@ int usbvision_power_off(struct usb_usbvision *usbvision);
 int usbvision_power_on(struct usb_usbvision *usbvision);
 
 #endif									/* __LINUX_USBVISION_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 6a4b0b8cd270..cf27006c29dc 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -138,6 +138,11 @@ static struct uvc_format_desc uvc_fmts[] = {
 		.fcc		= V4L2_PIX_FMT_RGB565,
 	},
 	{
+		.name		= "BGR 8:8:8 (BGR3)",
+		.guid		= UVC_GUID_FORMAT_BGR3,
+		.fcc		= V4L2_PIX_FMT_BGR24,
+	},
+	{
 		.name		= "H.264",
 		.guid		= UVC_GUID_FORMAT_H264,
 		.fcc		= V4L2_PIX_FMT_H264,
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index cc960723b926..10c554e7655c 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -143,20 +143,6 @@ static void uvc_buffer_finish(struct vb2_buffer *vb)
 		uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
 }
 
-static void uvc_wait_prepare(struct vb2_queue *vq)
-{
-	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-
-	mutex_unlock(&queue->mutex);
-}
-
-static void uvc_wait_finish(struct vb2_queue *vq)
-{
-	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-
-	mutex_lock(&queue->mutex);
-}
-
 static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
@@ -195,8 +181,8 @@ static struct vb2_ops uvc_queue_qops = {
 	.buf_prepare = uvc_buffer_prepare,
 	.buf_queue = uvc_buffer_queue,
 	.buf_finish = uvc_buffer_finish,
-	.wait_prepare = uvc_wait_prepare,
-	.wait_finish = uvc_wait_finish,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
 	.start_streaming = uvc_start_streaming,
 	.stop_streaming = uvc_stop_streaming,
 };
@@ -214,6 +200,7 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
 	queue->queue.mem_ops = &vb2_vmalloc_memops;
 	queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
 		| V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
+	queue->queue.lock = &queue->mutex;
 	ret = vb2_queue_init(&queue->queue);
 	if (ret)
 		return ret;
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 9c5cbcf16529..43e953f73e02 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -13,7 +13,6 @@
 
 #include <linux/compat.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/slab.h>
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 9637e8b86949..20ccc9d315dc 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1734,13 +1734,13 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
 
 	uvc_video_clock_reset(stream);
 
+	if (!uvc_queue_streaming(&stream->queue))
+		return 0;
+
 	ret = uvc_commit_video(stream, &stream->ctrl);
 	if (ret < 0)
 		return ret;
 
-	if (!uvc_queue_streaming(&stream->queue))
-		return 0;
-
 	return uvc_init_video(stream, GFP_NOIO);
 }
 
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index f0a04b532ede..c63e5b55e143 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -109,6 +109,9 @@
 #define UVC_GUID_FORMAT_RGBP \
 	{ 'R',  'G',  'B',  'P', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BGR3 \
+	{ 0x7d, 0xeb, 0x36, 0xe4, 0x4f, 0x52, 0xce, 0x11, \
+	 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}
 #define UVC_GUID_FORMAT_M420 \
 	{ 'M',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index 5c006277b8b1..ca850316d379 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -1454,8 +1454,6 @@ static int zr364xx_probe(struct usb_interface *intf,
 	cam->vdev.v4l2_dev = &cam->v4l2_dev;
 	cam->vdev.ctrl_handler = &cam->ctrl_handler;
 	video_set_drvdata(&cam->vdev, cam);
-	if (debug)
-		cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
 
 	cam->udev = udev;
 
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 9aa530a8bea9..86bb93fd7db8 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -47,15 +47,15 @@ static ssize_t index_show(struct device *cd,
 }
 static DEVICE_ATTR_RO(index);
 
-static ssize_t debug_show(struct device *cd,
+static ssize_t dev_debug_show(struct device *cd,
 			  struct device_attribute *attr, char *buf)
 {
 	struct video_device *vdev = to_video_device(cd);
 
-	return sprintf(buf, "%i\n", vdev->debug);
+	return sprintf(buf, "%i\n", vdev->dev_debug);
 }
 
-static ssize_t debug_store(struct device *cd, struct device_attribute *attr,
+static ssize_t dev_debug_store(struct device *cd, struct device_attribute *attr,
 			  const char *buf, size_t len)
 {
 	struct video_device *vdev = to_video_device(cd);
@@ -66,10 +66,10 @@ static ssize_t debug_store(struct device *cd, struct device_attribute *attr,
 	if (res)
 		return res;
 
-	vdev->debug = value;
+	vdev->dev_debug = value;
 	return len;
 }
-static DEVICE_ATTR_RW(debug);
+static DEVICE_ATTR_RW(dev_debug);
 
 static ssize_t name_show(struct device *cd,
 			 struct device_attribute *attr, char *buf)
@@ -82,7 +82,7 @@ static DEVICE_ATTR_RO(name);
 
 static struct attribute *video_device_attrs[] = {
 	&dev_attr_name.attr,
-	&dev_attr_debug.attr,
+	&dev_attr_dev_debug.attr,
 	&dev_attr_index.attr,
 	NULL,
 };
@@ -304,7 +304,8 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
 		return -EINVAL;
 	if (video_is_registered(vdev))
 		ret = vdev->fops->read(filp, buf, sz, off);
-	if (vdev->debug)
+	if ((vdev->dev_debug & V4L2_DEV_DEBUG_FOP) &&
+	    (vdev->dev_debug & V4L2_DEV_DEBUG_STREAMING))
 		printk(KERN_DEBUG "%s: read: %zd (%d)\n",
 			video_device_node_name(vdev), sz, ret);
 	return ret;
@@ -320,7 +321,8 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 		return -EINVAL;
 	if (video_is_registered(vdev))
 		ret = vdev->fops->write(filp, buf, sz, off);
-	if (vdev->debug)
+	if ((vdev->dev_debug & V4L2_DEV_DEBUG_FOP) &&
+	    (vdev->dev_debug & V4L2_DEV_DEBUG_STREAMING))
 		printk(KERN_DEBUG "%s: write: %zd (%d)\n",
 			video_device_node_name(vdev), sz, ret);
 	return ret;
@@ -335,7 +337,7 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 		return DEFAULT_POLLMASK;
 	if (video_is_registered(vdev))
 		res = vdev->fops->poll(filp, poll);
-	if (vdev->debug > 2)
+	if (vdev->dev_debug & V4L2_DEV_DEBUG_POLL)
 		printk(KERN_DEBUG "%s: poll: %08x\n",
 			video_device_node_name(vdev), res);
 	return res;
@@ -404,7 +406,7 @@ static unsigned long v4l2_get_unmapped_area(struct file *filp,
 	if (!video_is_registered(vdev))
 		return -ENODEV;
 	ret = vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags);
-	if (vdev->debug)
+	if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
 		printk(KERN_DEBUG "%s: get_unmapped_area (%d)\n",
 			video_device_node_name(vdev), ret);
 	return ret;
@@ -420,7 +422,7 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 		return -ENODEV;
 	if (video_is_registered(vdev))
 		ret = vdev->fops->mmap(filp, vm);
-	if (vdev->debug)
+	if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
 		printk(KERN_DEBUG "%s: mmap (%d)\n",
 			video_device_node_name(vdev), ret);
 	return ret;
@@ -450,7 +452,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 			ret = -ENODEV;
 	}
 
-	if (vdev->debug)
+	if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
 		printk(KERN_DEBUG "%s: open (%d)\n",
 			video_device_node_name(vdev), ret);
 	/* decrease the refcount in case of an error */
@@ -467,7 +469,7 @@ static int v4l2_release(struct inode *inode, struct file *filp)
 
 	if (vdev->fops->release)
 		ret = vdev->fops->release(filp);
-	if (vdev->debug)
+	if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
 		printk(KERN_DEBUG "%s: release\n",
 			video_device_node_name(vdev));
 
@@ -1033,10 +1035,3 @@ MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR);
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index faac2f4e0f3a..b08407225db1 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2339,7 +2339,7 @@ static long __video_do_ioctl(struct file *file,
 	const struct v4l2_ioctl_info *info;
 	void *fh = file->private_data;
 	struct v4l2_fh *vfh = NULL;
-	int debug = vfd->debug;
+	int dev_debug = vfd->dev_debug;
 	long ret = -ENOTTY;
 
 	if (ops == NULL) {
@@ -2388,11 +2388,15 @@ static long __video_do_ioctl(struct file *file,
 	}
 
 done:
-	if (debug) {
+	if (dev_debug & (V4L2_DEV_DEBUG_IOCTL | V4L2_DEV_DEBUG_IOCTL_ARG)) {
+		if (!(dev_debug & V4L2_DEV_DEBUG_STREAMING) &&
+		    (cmd == VIDIOC_QBUF || cmd == VIDIOC_DQBUF))
+			return ret;
+
 		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
 		if (ret < 0)
 			pr_cont(": error %ld", ret);
-		if (debug == V4L2_DEBUG_IOCTL)
+		if (!(dev_debug & V4L2_DEV_DEBUG_IOCTL_ARG))
 			pr_cont("\n");
 		else if (_IOC_DIR(cmd) == _IOC_NONE)
 			info->debug(arg, write_only);
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 543631c3557a..19a034e79be4 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -283,10 +283,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		if (rval)
 			return rval;
 
-		rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop);
-		if (rval != -ENOIOCTLCMD)
-			return rval;
-
 		memset(&sel, 0, sizeof(sel));
 		sel.which = crop->which;
 		sel.pad = crop->pad;
@@ -308,10 +304,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		if (rval)
 			return rval;
 
-		rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop);
-		if (rval != -ENOIOCTLCMD)
-			return rval;
-
 		memset(&sel, 0, sizeof(sel));
 		sel.which = crop->which;
 		sel.pad = crop->pad;
diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 3ff15f1c9d70..f669cedca8bd 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -145,12 +145,11 @@ struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf)
 }
 EXPORT_SYMBOL_GPL(videobuf_to_dma);
 
-void videobuf_dma_init(struct videobuf_dmabuf *dma)
+static void videobuf_dma_init(struct videobuf_dmabuf *dma)
 {
 	memset(dma, 0, sizeof(*dma));
 	dma->magic = MAGIC_DMABUF;
 }
-EXPORT_SYMBOL_GPL(videobuf_dma_init);
 
 static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 			int direction, unsigned long data, unsigned long size)
@@ -195,7 +194,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 	return 0;
 }
 
-int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
+static int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
 			   unsigned long data, unsigned long size)
 {
 	int ret;
@@ -206,9 +205,8 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
 
-int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
+static int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
 			     int nr_pages)
 {
 	int i;
@@ -267,9 +265,8 @@ out_free_pages:
 	return -ENOMEM;
 
 }
-EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
 
-int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
+static int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
 			      dma_addr_t addr, int nr_pages)
 {
 	dprintk(1, "init overlay [%d pages @ bus 0x%lx]\n",
@@ -284,9 +281,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
 
-int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
+static int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
 {
 	MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
 	BUG_ON(0 == dma->nr_pages);
@@ -328,7 +324,6 @@ int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(videobuf_dma_map);
 
 int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma)
 {
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index fba944e50227..bcde88572429 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -95,7 +95,7 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 		if (vb2_get_contig_userptr(vaddr, size, &vma, &physp))
 			goto fail_pages_array_alloc;
 		buf->vma = vma;
-		buf->vaddr = ioremap_nocache(physp, size);
+		buf->vaddr = (__force void *)ioremap_nocache(physp, size);
 		if (!buf->vaddr)
 			goto fail_pages_array_alloc;
 	} else {
@@ -155,7 +155,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv)
 		kfree(buf->pages);
 	} else {
 		vb2_put_vma(buf->vma);
-		iounmap(buf->vaddr);
+		iounmap((__force void __iomem *)buf->vaddr);
 	}
 	kfree(buf);
 }
@@ -211,6 +211,7 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
 	return 0;
 }
 
+#ifdef CONFIG_HAS_DMA
 /*********************************************/
 /*         DMABUF ops for exporters          */
 /*********************************************/
@@ -380,6 +381,8 @@ static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flag
 
 	return dbuf;
 }
+#endif /* CONFIG_HAS_DMA */
+
 
 /*********************************************/
 /*       callbacks for DMABUF buffers        */
@@ -437,7 +440,9 @@ const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.put		= vb2_vmalloc_put,
 	.get_userptr	= vb2_vmalloc_get_userptr,
 	.put_userptr	= vb2_vmalloc_put_userptr,
+#ifdef CONFIG_HAS_DMA
 	.get_dmabuf	= vb2_vmalloc_get_dmabuf,
+#endif
 	.map_dmabuf	= vb2_vmalloc_map_dmabuf,
 	.unmap_dmabuf	= vb2_vmalloc_unmap_dmabuf,
 	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 2a054a99d433..96498b7fc20e 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -27,18 +27,12 @@ source "drivers/staging/media/davinci_vpfe/Kconfig"
 
 source "drivers/staging/media/dt3155v4l/Kconfig"
 
-source "drivers/staging/media/tlg2300/Kconfig"
-
 source "drivers/staging/media/mn88472/Kconfig"
 
 source "drivers/staging/media/mn88473/Kconfig"
 
 source "drivers/staging/media/omap4iss/Kconfig"
 
-source "drivers/staging/media/parport/Kconfig"
-
-source "drivers/staging/media/vino/Kconfig"
-
 # Keep LIRC at the end, as it has sub-menus
 source "drivers/staging/media/lirc/Kconfig"
 
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 412b28408398..a9006bcb4472 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -6,7 +6,3 @@ obj-$(CONFIG_VIDEO_DM365_VPFE)	+= davinci_vpfe/
 obj-$(CONFIG_VIDEO_OMAP4)	+= omap4iss/
 obj-$(CONFIG_DVB_MN88472)       += mn88472/
 obj-$(CONFIG_DVB_MN88473)       += mn88473/
-obj-y				+= parport/
-obj-$(CONFIG_VIDEO_TLG2300)	+= tlg2300/
-obj-y                           += vino/
-
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
index 60a57b2a8fb2..538250667918 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.c
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.c
@@ -2684,9 +2684,7 @@ static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client)
 		vd = bdev->videodev;
 
 		bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs));
-
-		if (vd)
-			video_unregister_device(vd);
+		video_unregister_device(vd);
 
 		if (bdev->power_state)
 			bcm2048_set_power_state(bdev, BCM2048_POWER_OFF);
@@ -2699,8 +2697,6 @@ static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client)
 		kfree(bdev);
 	}
 
-	i2c_set_clientdata(client, NULL);
-
 	return 0;
 }
 
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
index 0ba0bf2c1cff..bcf762bc233d 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
@@ -1535,7 +1535,7 @@ isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 }
 
 /*
- * isif_pad_set_crop() - set crop rectangle on pad
+ * isif_pad_set_selection() - set crop rectangle on pad
  * @sd: VPFE isif V4L2 subdevice
  * @fh: V4L2 subdev file handle
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
@@ -1543,35 +1543,36 @@ isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
  * Return 0 on success, -EINVAL if pad is invalid
  */
 static int
-isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-		  struct v4l2_subdev_crop *crop)
+isif_pad_set_selection(struct v4l2_subdev *sd,
+		       struct v4l2_subdev_fh *fh,
+		       struct v4l2_subdev_selection *sel)
 {
 	struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
 	struct v4l2_mbus_framefmt *format;
 
-	/* check wether its a valid pad */
-	if (crop->pad != ISIF_PAD_SINK)
+	/* check whether it's a valid pad and target */
+	if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP)
 		return -EINVAL;
 
-	format = __isif_get_format(vpfe_isif, fh, crop->pad, crop->which);
+	format = __isif_get_format(vpfe_isif, fh, sel->pad, sel->which);
 	if (format == NULL)
 		return -EINVAL;
 
 	/* check wether crop rect is within limits */
-	if (crop->rect.top < 0 || crop->rect.left < 0 ||
-		(crop->rect.left + crop->rect.width >
+	if (sel->r.top < 0 || sel->r.left < 0 ||
+		(sel->r.left + sel->r.width >
 		vpfe_isif->formats[ISIF_PAD_SINK].width) ||
-		(crop->rect.top + crop->rect.height >
+		(sel->r.top + sel->r.height >
 			vpfe_isif->formats[ISIF_PAD_SINK].height)) {
-		crop->rect.left = 0;
-		crop->rect.top = 0;
-		crop->rect.width = format->width;
-		crop->rect.height = format->height;
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = format->width;
+		sel->r.height = format->height;
 	}
 	/* adjust the width to 16 pixel boundary */
-	crop->rect.width = ((crop->rect.width + 15) & ~0xf);
-	vpfe_isif->crop = crop->rect;
-	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+	sel->r.width = ((sel->r.width + 15) & ~0xf);
+	vpfe_isif->crop = sel->r;
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 		isif_set_image_window(vpfe_isif);
 	} else {
 		struct v4l2_rect *rect;
@@ -1583,7 +1584,7 @@ isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 }
 
 /*
- * isif_pad_get_crop() - get crop rectangle on pad
+ * isif_pad_get_selection() - get crop rectangle on pad
  * @sd: VPFE isif V4L2 subdevice
  * @fh: V4L2 subdev file handle
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
@@ -1591,22 +1592,23 @@ isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
  * Return 0 on success, -EINVAL if pad is invalid
  */
 static int
-isif_pad_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-		  struct v4l2_subdev_crop *crop)
+isif_pad_get_selection(struct v4l2_subdev *sd,
+		       struct v4l2_subdev_fh *fh,
+		       struct v4l2_subdev_selection *sel)
 {
 	struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
 
-	/* check wether its a valid pad */
-	if (crop->pad != ISIF_PAD_SINK)
+	/* check whether it's a valid pad and target */
+	if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP)
 		return -EINVAL;
 
-	if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+	if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
 		struct v4l2_rect *rect;
 
 		rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
-		memcpy(&crop->rect, rect, sizeof(*rect));
+		memcpy(&sel->r, rect, sizeof(*rect));
 	} else {
-		crop->rect = vpfe_isif->crop;
+		sel->r = vpfe_isif->crop;
 	}
 
 	return 0;
@@ -1626,7 +1628,7 @@ isif_init_formats(struct v4l2_subdev *sd,
 		  struct v4l2_subdev_fh *fh)
 {
 	struct v4l2_subdev_format format;
-	struct v4l2_subdev_crop crop;
+	struct v4l2_subdev_selection sel;
 
 	memset(&format, 0, sizeof(format));
 	format.pad = ISIF_PAD_SINK;
@@ -1644,12 +1646,13 @@ isif_init_formats(struct v4l2_subdev *sd,
 	format.format.height = MAX_HEIGHT;
 	isif_set_format(sd, fh, &format);
 
-	memset(&crop, 0, sizeof(crop));
-	crop.pad = ISIF_PAD_SINK;
-	crop.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-	crop.rect.width = MAX_WIDTH;
-	crop.rect.height = MAX_HEIGHT;
-	isif_pad_set_crop(sd, fh, &crop);
+	memset(&sel, 0, sizeof(sel));
+	sel.pad = ISIF_PAD_SINK;
+	sel.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	sel.target = V4L2_SEL_TGT_CROP;
+	sel.r.width = MAX_WIDTH;
+	sel.r.height = MAX_HEIGHT;
+	isif_pad_set_selection(sd, fh, &sel);
 
 	return 0;
 }
@@ -1675,8 +1678,8 @@ static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = {
 	.enum_frame_size = isif_enum_frame_size,
 	.get_fmt = isif_get_format,
 	.set_fmt = isif_set_format,
-	.set_crop = isif_pad_set_crop,
-	.get_crop = isif_pad_get_crop,
+	.set_selection = isif_pad_set_selection,
+	.get_selection = isif_pad_get_selection,
 };
 
 /* subdev operations */
diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
index eb4ccb8d2a93..19628d0104ab 100644
--- a/drivers/staging/media/lirc/lirc_serial.c
+++ b/drivers/staging/media/lirc/lirc_serial.c
@@ -107,7 +107,7 @@ static int io;
 static int irq;
 static bool iommap;
 static int ioshift;
-static bool softcarrier = 1;
+static bool softcarrier = true;
 static bool share_irq;
 static bool debug;
 static int sense = -1;	/* -1 = auto, 0 = active high, 1 = active low */
@@ -266,7 +266,7 @@ static unsigned long space_width;
 /* fetch serial input packet (1 byte) from register offset */
 static u8 sinp(int offset)
 {
-	if (iommap != 0)
+	if (iommap)
 		/* the register is memory-mapped */
 		offset <<= ioshift;
 
@@ -276,7 +276,7 @@ static u8 sinp(int offset)
 /* write serial output packet (1 byte) of value to register offset */
 static void soutp(int offset, u8 value)
 {
-	if (iommap != 0)
+	if (iommap)
 		/* the register is memory-mapped */
 		offset <<= ioshift;
 
@@ -799,10 +799,10 @@ static int lirc_serial_probe(struct platform_device *dev)
 	 * For memory mapped I/O you *might* need to use ioremap() first,
 	 * for the NSLU2 it's done in boot code.
 	 */
-	if (((iommap != 0)
+	if (((iommap)
 	     && (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift,
 					 LIRC_DRIVER_NAME) == NULL))
-	   || ((iommap == 0)
+	   || ((!iommap)
 	       && (devm_request_region(&dev->dev, io, 8,
 				       LIRC_DRIVER_NAME) == NULL))) {
 		dev_err(&dev->dev, "port %04x already in use\n", io);
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index cc872fb4ca68..e16627ca488e 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -369,17 +369,17 @@ static int add_to_buf(struct IR *ir)
 		ret = i2c_master_send(rx->c, sendbuf, 1);
 		if (ret != 1) {
 			dev_err(ir->l.dev, "i2c_master_send failed with %d\n",
-					   ret);
+				ret);
 			if (failures >= 3) {
 				mutex_unlock(&ir->ir_lock);
-				dev_err(ir->l.dev, "unable to read from the IR chip "
-					    "after 3 resets, giving up\n");
+				dev_err(ir->l.dev,
+					"unable to read from the IR chip after 3 resets, giving up\n");
 				break;
 			}
 
 			/* Looks like the chip crashed, reset it */
-			dev_err(ir->l.dev, "polling the IR receiver chip failed, "
-				    "trying reset\n");
+			dev_err(ir->l.dev,
+				"polling the IR receiver chip failed, trying reset\n");
 
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			if (kthread_should_stop()) {
@@ -405,14 +405,16 @@ static int add_to_buf(struct IR *ir)
 		ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf));
 		mutex_unlock(&ir->ir_lock);
 		if (ret != sizeof(keybuf)) {
-			dev_err(ir->l.dev, "i2c_master_recv failed with %d -- "
-				    "keeping last read buffer\n", ret);
+			dev_err(ir->l.dev,
+				"i2c_master_recv failed with %d -- keeping last read buffer\n",
+				ret);
 		} else {
 			rx->b[0] = keybuf[3];
 			rx->b[1] = keybuf[4];
 			rx->b[2] = keybuf[5];
-			dev_dbg(ir->l.dev, "key (0x%02x/0x%02x)\n",
-					   rx->b[0], rx->b[1]);
+			dev_dbg(ir->l.dev,
+				"key (0x%02x/0x%02x)\n",
+				rx->b[0], rx->b[1]);
 		}
 
 		/* key pressed ? */
@@ -656,8 +658,8 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
 		dev_dbg(tx->ir->l.dev, "%*ph", 5, buf);
 		ret = i2c_master_send(tx->c, buf, tosend + 1);
 		if (ret != tosend + 1) {
-			dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n",
-					       ret);
+			dev_err(tx->ir->l.dev,
+				"i2c_master_send failed with %d\n", ret);
 			return ret < 0 ? ret : -EFAULT;
 		}
 		i += tosend;
@@ -710,11 +712,12 @@ static int send_boot_data(struct IR_tx *tx)
 	}
 	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
 		dev_err(tx->ir->l.dev, "unexpected IR TX init response: %02x\n",
-				       buf[0]);
+			buf[0]);
 		return 0;
 	}
-	dev_notice(tx->ir->l.dev, "Zilog/Hauppauge IR blaster firmware version "
-		     "%d.%d.%d loaded\n", buf[1], buf[2], buf[3]);
+	dev_notice(tx->ir->l.dev,
+		   "Zilog/Hauppauge IR blaster firmware version %d.%d.%d loaded\n",
+		   buf[1], buf[2], buf[3]);
 
 	return 0;
 }
@@ -759,8 +762,9 @@ static int fw_load(struct IR_tx *tx)
 	/* Request codeset data file */
 	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev);
 	if (ret != 0) {
-		dev_err(tx->ir->l.dev, "firmware haup-ir-blaster.bin not available (%d)\n",
-			    ret);
+		dev_err(tx->ir->l.dev,
+			"firmware haup-ir-blaster.bin not available (%d)\n",
+			ret);
 		ret = ret < 0 ? ret : -EFAULT;
 		goto out;
 	}
@@ -792,9 +796,9 @@ static int fw_load(struct IR_tx *tx)
 	if (!read_uint8(&data, tx_data->endp, &version))
 		goto corrupt;
 	if (version != 1) {
-		dev_err(tx->ir->l.dev, "unsupported code set file version (%u, expected"
-			    "1) -- please upgrade to a newer driver",
-			    version);
+		dev_err(tx->ir->l.dev,
+			"unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver\n",
+			version);
 		fw_unload_locked();
 		ret = -EFAULT;
 		goto out;
@@ -810,7 +814,7 @@ static int fw_load(struct IR_tx *tx)
 		goto corrupt;
 
 	dev_dbg(tx->ir->l.dev, "%u IR blaster codesets loaded\n",
-			       tx_data->num_code_sets);
+		tx_data->num_code_sets);
 
 	tx_data->code_sets = vmalloc(
 		tx_data->num_code_sets * sizeof(char *));
@@ -940,8 +944,9 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 			unsigned char buf[MAX_XFER_SIZE];
 
 			if (rbuf->chunk_size > sizeof(buf)) {
-				dev_err(ir->l.dev, "chunk_size is too big (%d)!\n",
-					    rbuf->chunk_size);
+				dev_err(ir->l.dev,
+					"chunk_size is too big (%d)!\n",
+					rbuf->chunk_size);
 				ret = -EINVAL;
 				break;
 			}
@@ -964,8 +969,8 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 	put_ir_rx(rx, false);
 	set_current_state(TASK_RUNNING);
 
-	dev_dbg(ir->l.dev, "read result = %d (%s)\n",
-			   ret, ret ? "Error" : "OK");
+	dev_dbg(ir->l.dev, "read result = %d (%s)\n", ret,
+		ret ? "Error" : "OK");
 
 	return ret ? ret : written;
 }
@@ -981,8 +986,9 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	ret = get_key_data(data_block, code, key);
 
 	if (ret == -EPROTO) {
-		dev_err(tx->ir->l.dev, "failed to get data for code %u, key %u -- check "
-			    "lircd.conf entries\n", code, key);
+		dev_err(tx->ir->l.dev,
+			"failed to get data for code %u, key %u -- check lircd.conf entries\n",
+			code, key);
 		return ret;
 	} else if (ret != 0)
 		return ret;
@@ -1057,12 +1063,14 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 		ret = i2c_master_send(tx->c, buf, 1);
 		if (ret == 1)
 			break;
-		dev_dbg(tx->ir->l.dev, "NAK expected: i2c_master_send "
-			"failed with %d (try %d)\n", ret, i+1);
+		dev_dbg(tx->ir->l.dev,
+			"NAK expected: i2c_master_send failed with %d (try %d)\n",
+			ret, i+1);
 	}
 	if (ret != 1) {
-		dev_err(tx->ir->l.dev, "IR TX chip never got ready: last i2c_master_send "
-			    "failed with %d\n", ret);
+		dev_err(tx->ir->l.dev,
+			"IR TX chip never got ready: last i2c_master_send failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -1074,7 +1082,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	}
 	if (buf[0] != 0x80) {
 		dev_err(tx->ir->l.dev, "unexpected IR TX response #2: %02x\n",
-				       buf[0]);
+			buf[0]);
 		return -EFAULT;
 	}
 
@@ -1165,12 +1173,12 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		 */
 		if (ret != 0) {
 			/* Looks like the chip crashed, reset it */
-			dev_err(tx->ir->l.dev, "sending to the IR transmitter chip "
-				    "failed, trying reset\n");
+			dev_err(tx->ir->l.dev,
+				"sending to the IR transmitter chip failed, trying reset\n");
 
 			if (failures >= 3) {
-				dev_err(tx->ir->l.dev, "unable to send to the IR chip "
-					    "after 3 resets, giving up\n");
+				dev_err(tx->ir->l.dev,
+					"unable to send to the IR chip after 3 resets, giving up\n");
 				mutex_unlock(&ir->ir_lock);
 				mutex_unlock(&tx->client_lock);
 				put_ir_tx(tx, false);
@@ -1226,7 +1234,7 @@ static unsigned int poll(struct file *filep, poll_table *wait)
 	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM);
 
 	dev_dbg(ir->l.dev, "poll result = %s\n",
-			   ret ? "POLLIN|POLLRDNORM" : "none");
+		ret ? "POLLIN|POLLRDNORM" : "none");
 	return ret;
 }
 
@@ -1333,7 +1341,8 @@ static int close(struct inode *node, struct file *filep)
 	struct IR *ir = filep->private_data;
 
 	if (ir == NULL) {
-		dev_err(ir->l.dev, "close: no private_data attached to the file!\n");
+		dev_err(ir->l.dev,
+			"close: no private_data attached to the file!\n");
 		return -ENODEV;
 	}
 
@@ -1540,8 +1549,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 		/* Proceed only if the Rx client is also ready or not needed */
 		if (rx == NULL && !tx_only) {
-			dev_info(tx->ir->l.dev, "probe of IR Tx on %s (i2c-%d) done. Waiting"
-				   " on IR Rx.\n", adap->name, adap->nr);
+			dev_info(tx->ir->l.dev,
+				 "probe of IR Tx on %s (i2c-%d) done. Waiting on IR Rx.\n",
+				 adap->name, adap->nr);
 			goto out_ok;
 		}
 	} else {
@@ -1579,8 +1589,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				       "zilog-rx-i2c-%d", adap->nr);
 		if (IS_ERR(rx->task)) {
 			ret = PTR_ERR(rx->task);
-			dev_err(tx->ir->l.dev, "%s: could not start IR Rx polling thread"
-				    "\n", __func__);
+			dev_err(tx->ir->l.dev,
+				"%s: could not start IR Rx polling thread\n",
+				__func__);
 			/* Failed kthread, so put back the ir ref */
 			put_ir_device(ir, true);
 			/* Failure exit, so put back rx ref from i2c_client */
@@ -1592,8 +1603,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 		/* Proceed only if the Tx client is also ready */
 		if (tx == NULL) {
-			pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting"
-				   " on IR Tx.\n", adap->name, adap->nr);
+			pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting on IR Tx.\n",
+				   adap->name, adap->nr);
 			goto out_ok;
 		}
 	}
@@ -1602,13 +1613,15 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	ir->l.minor = minor; /* module option: user requested minor number */
 	ir->l.minor = lirc_register_driver(&ir->l);
 	if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
-		dev_err(tx->ir->l.dev, "%s: \"minor\" must be between 0 and %d (%d)!\n",
-			    __func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
+		dev_err(tx->ir->l.dev,
+			"%s: \"minor\" must be between 0 and %d (%d)!\n",
+			__func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
 		ret = -EBADRQC;
 		goto out_put_xx;
 	}
-	dev_info(ir->l.dev, "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
-		   adap->name, adap->nr, ir->l.minor);
+	dev_info(ir->l.dev,
+		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
+		 adap->name, adap->nr, ir->l.minor);
 
 out_ok:
 	if (rx != NULL)
@@ -1616,8 +1629,9 @@ out_ok:
 	if (tx != NULL)
 		put_ir_tx(tx, true);
 	put_ir_device(ir, true);
-	dev_info(ir->l.dev, "probe of IR %s on %s (i2c-%d) done\n",
-		   tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
+	dev_info(ir->l.dev,
+		 "probe of IR %s on %s (i2c-%d) done\n",
+		 tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
 	mutex_unlock(&ir_devices_lock);
 	return 0;
 
@@ -1629,9 +1643,9 @@ out_put_xx:
 out_put_ir:
 	put_ir_device(ir, true);
 out_no_ir:
-	dev_err(&client->dev, "%s: probing IR %s on %s (i2c-%d) failed with %d\n",
-		    __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr,
-		   ret);
+	dev_err(&client->dev,
+		"%s: probing IR %s on %s (i2c-%d) failed with %d\n",
+		__func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, ret);
 	mutex_unlock(&ir_devices_lock);
 	return ret;
 }
diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c
index 52de8f85d36c..6eebe564e557 100644
--- a/drivers/staging/media/mn88472/mn88472.c
+++ b/drivers/staging/media/mn88472/mn88472.c
@@ -30,6 +30,7 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, i;
 	u32 if_frequency = 0;
+	u64 tmp;
 	u8 delivery_system_val, if_val[3], bw_val[7], bw_val2;
 
 	dev_dbg(&client->dev,
@@ -57,36 +58,22 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	switch (c->delivery_system) {
-	case SYS_DVBT:
-	case SYS_DVBT2:
-		if (c->bandwidth_hz <= 6000000) {
-			/* IF 3570000 Hz, BW 6000000 Hz */
-			memcpy(if_val, "\x2c\x94\xdb", 3);
-			memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7);
-			bw_val2 = 0x02;
-		} else if (c->bandwidth_hz <= 7000000) {
-			/* IF 4570000 Hz, BW 7000000 Hz */
-			memcpy(if_val, "\x39\x11\xbc", 3);
-			memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7);
-			bw_val2 = 0x01;
-		} else if (c->bandwidth_hz <= 8000000) {
-			/* IF 4570000 Hz, BW 8000000 Hz */
-			memcpy(if_val, "\x39\x11\xbc", 3);
-			memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7);
-			bw_val2 = 0x00;
-		} else {
-			ret = -EINVAL;
-			goto err;
-		}
-		break;
-	case SYS_DVBC_ANNEX_A:
-		/* IF 5070000 Hz, BW 8000000 Hz */
-		memcpy(if_val, "\x3f\x50\x2c", 3);
+	if (c->bandwidth_hz <= 5000000) {
+		memcpy(bw_val, "\xe5\x99\x9a\x1b\xa9\x1b\xa9", 7);
+		bw_val2 = 0x03;
+	} else if (c->bandwidth_hz <= 6000000) {
+		/* IF 3570000 Hz, BW 6000000 Hz */
+		memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7);
+		bw_val2 = 0x02;
+	} else if (c->bandwidth_hz <= 7000000) {
+		/* IF 4570000 Hz, BW 7000000 Hz */
+		memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7);
+		bw_val2 = 0x01;
+	} else if (c->bandwidth_hz <= 8000000) {
+		/* IF 4570000 Hz, BW 8000000 Hz */
 		memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7);
 		bw_val2 = 0x00;
-		break;
-	default:
+	} else {
 		ret = -EINVAL;
 		goto err;
 	}
@@ -106,17 +93,12 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 		dev_dbg(&client->dev, "get_if_frequency=%d\n", if_frequency);
 	}
 
-	switch (if_frequency) {
-	case 3570000:
-	case 4570000:
-	case 5070000:
-		break;
-	default:
-		dev_err(&client->dev, "IF frequency %d not supported\n",
-				if_frequency);
-		ret = -EINVAL;
-		goto err;
-	}
+	/* Calculate IF registers ( (1<<24)*IF / Xtal ) */
+	tmp =  div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2),
+				   dev->xtal);
+	if_val[0] = ((tmp >> 16) & 0xff);
+	if_val[1] = ((tmp >>  8) & 0xff);
+	if_val[2] = ((tmp >>  0) & 0xff);
 
 	ret = regmap_write(dev->regmap[2], 0xfb, 0x13);
 	ret = regmap_write(dev->regmap[2], 0xef, 0x13);
@@ -198,6 +180,8 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 	ret = regmap_write(dev->regmap[0], 0xae, 0x00);
 	ret = regmap_write(dev->regmap[2], 0x08, 0x1d);
 	ret = regmap_write(dev->regmap[0], 0xd9, 0xe3);
+
+	/* Reset demod */
 	ret = regmap_write(dev->regmap[2], 0xf8, 0x9f);
 	if (ret)
 		goto err;
@@ -411,6 +395,7 @@ static int mn88472_probe(struct i2c_client *client,
 	}
 
 	dev->i2c_wr_max = config->i2c_wr_max;
+	dev->xtal = config->xtal;
 	dev->client[0] = client;
 	dev->regmap[0] = regmap_init_i2c(dev->client[0], &regmap_config);
 	if (IS_ERR(dev->regmap[0])) {
diff --git a/drivers/staging/media/mn88472/mn88472_priv.h b/drivers/staging/media/mn88472/mn88472_priv.h
index 1095949f040d..b12b731e2d4e 100644
--- a/drivers/staging/media/mn88472/mn88472_priv.h
+++ b/drivers/staging/media/mn88472/mn88472_priv.h
@@ -31,6 +31,7 @@ struct mn88472_dev {
 	u16 i2c_wr_max;
 	fe_delivery_system_t delivery_system;
 	bool warm; /* FW running */
+	u32 xtal;
 };
 
 #endif
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
index cc1dfadd91eb..44b81a2c8b6f 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -560,41 +560,28 @@ static int iss_pipeline_link_notify(struct media_link *link, u32 flags,
  */
 
 /*
- * iss_pipeline_enable - Enable streaming on a pipeline
+ * iss_pipeline_disable - Disable streaming on a pipeline
  * @pipe: ISS pipeline
- * @mode: Stream mode (single shot or continuous)
+ * @until: entity at which to stop pipeline walk
  *
- * Walk the entities chain starting at the pipeline output video node and start
- * all modules in the chain in the given mode.
+ * Walk the entities chain starting at the pipeline output video node and stop
+ * all modules in the chain. Wait synchronously for the modules to be stopped if
+ * necessary.
  *
- * Return 0 if successful, or the return value of the failed video::s_stream
- * operation otherwise.
+ * If the until argument isn't NULL, stop the pipeline walk when reaching the
+ * until entity. This is used to disable a partially started pipeline due to a
+ * subdev start error.
  */
-static int iss_pipeline_enable(struct iss_pipeline *pipe,
-			       enum iss_pipeline_stream_state mode)
+static int iss_pipeline_disable(struct iss_pipeline *pipe,
+				struct media_entity *until)
 {
 	struct iss_device *iss = pipe->output->iss;
 	struct media_entity *entity;
 	struct media_pad *pad;
 	struct v4l2_subdev *subdev;
-	unsigned long flags;
+	int failure = 0;
 	int ret;
 
-	/* If one of the entities in the pipeline has crashed it will not work
-	 * properly. Refuse to start streaming in that case. This check must be
-	 * performed before the loop below to avoid starting entities if the
-	 * pipeline won't start anyway (those entities would then likely fail to
-	 * stop, making the problem worse).
-	 */
-	if (pipe->entities & iss->crashed)
-		return -EIO;
-
-	spin_lock_irqsave(&pipe->lock, flags);
-	pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT);
-	spin_unlock_irqrestore(&pipe->lock, flags);
-
-	pipe->do_propagation = false;
-
 	entity = &pipe->output->video.entity;
 	while (1) {
 		pad = &entity->pads[0];
@@ -607,33 +594,62 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		entity = pad->entity;
-		subdev = media_entity_to_v4l2_subdev(entity);
+		if (entity == until)
+			break;
 
-		ret = v4l2_subdev_call(subdev, video, s_stream, mode);
-		if (ret < 0 && ret != -ENOIOCTLCMD)
-			return ret;
+		subdev = media_entity_to_v4l2_subdev(entity);
+		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+		if (ret < 0) {
+			dev_dbg(iss->dev, "%s: module stop timeout.\n",
+				subdev->name);
+			/* If the entity failed to stopped, assume it has
+			 * crashed. Mark it as such, the ISS will be reset when
+			 * applications will release it.
+			 */
+			iss->crashed |= 1U << subdev->entity.id;
+			failure = -ETIMEDOUT;
+		}
 	}
-	iss_print_status(pipe->output->iss);
-	return 0;
+
+	return failure;
 }
 
 /*
- * iss_pipeline_disable - Disable streaming on a pipeline
+ * iss_pipeline_enable - Enable streaming on a pipeline
  * @pipe: ISS pipeline
+ * @mode: Stream mode (single shot or continuous)
  *
- * Walk the entities chain starting at the pipeline output video node and stop
- * all modules in the chain. Wait synchronously for the modules to be stopped if
- * necessary.
+ * Walk the entities chain starting at the pipeline output video node and start
+ * all modules in the chain in the given mode.
+ *
+ * Return 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise.
  */
-static int iss_pipeline_disable(struct iss_pipeline *pipe)
+static int iss_pipeline_enable(struct iss_pipeline *pipe,
+			       enum iss_pipeline_stream_state mode)
 {
 	struct iss_device *iss = pipe->output->iss;
 	struct media_entity *entity;
 	struct media_pad *pad;
 	struct v4l2_subdev *subdev;
-	int failure = 0;
+	unsigned long flags;
 	int ret;
 
+	/* If one of the entities in the pipeline has crashed it will not work
+	 * properly. Refuse to start streaming in that case. This check must be
+	 * performed before the loop below to avoid starting entities if the
+	 * pipeline won't start anyway (those entities would then likely fail to
+	 * stop, making the problem worse).
+	 */
+	if (pipe->entities & iss->crashed)
+		return -EIO;
+
+	spin_lock_irqsave(&pipe->lock, flags);
+	pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT);
+	spin_unlock_irqrestore(&pipe->lock, flags);
+
+	pipe->do_propagation = false;
+
 	entity = &pipe->output->video.entity;
 	while (1) {
 		pad = &entity->pads[0];
@@ -648,20 +664,19 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe)
 		entity = pad->entity;
 		subdev = media_entity_to_v4l2_subdev(entity);
 
-		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
-		if (ret < 0) {
-			dev_dbg(iss->dev, "%s: module stop timeout.\n",
-				subdev->name);
-			/* If the entity failed to stopped, assume it has
-			 * crashed. Mark it as such, the ISS will be reset when
-			 * applications will release it.
-			 */
-			iss->crashed |= 1U << subdev->entity.id;
-			failure = -ETIMEDOUT;
+		ret = v4l2_subdev_call(subdev, video, s_stream, mode);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			iss_pipeline_disable(pipe, entity);
+			return ret;
 		}
+
+		if (subdev == &iss->csi2a.subdev ||
+		    subdev == &iss->csi2b.subdev)
+			pipe->do_propagation = true;
 	}
 
-	return failure;
+	iss_print_status(pipe->output->iss);
+	return 0;
 }
 
 /*
@@ -682,7 +697,7 @@ int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
 	int ret;
 
 	if (state == ISS_PIPELINE_STREAM_STOPPED)
-		ret = iss_pipeline_disable(pipe);
+		ret = iss_pipeline_disable(pipe, NULL);
 	else
 		ret = iss_pipeline_enable(pipe, state);
 
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index 21971c675b8c..2d96fb3eca53 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -319,6 +319,8 @@ static void csi2_ctx_config(struct iss_csi2_device *csi2,
 {
 	u32 reg = 0;
 
+	ctx->frame = 0;
+
 	/* Set up CSI2_CTx_CTRL1 */
 	if (ctx->eof_enabled)
 		reg = CSI2_CTX_CTRL1_EOF_EN;
@@ -396,21 +398,18 @@ static void csi2_timing_config(struct iss_csi2_device *csi2,
  */
 static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable)
 {
-	u32 reg = CSI2_CTX_IRQ_FE;
+	const u32 mask = CSI2_CTX_IRQ_FE | CSI2_CTX_IRQ_FS;
 	int i;
 
-	if (csi2->use_fs_irq)
-		reg |= CSI2_CTX_IRQ_FS;
-
 	for (i = 0; i < 8; i++) {
 		iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i),
-			      reg);
+			      mask);
 		if (enable)
 			iss_reg_set(csi2->iss, csi2->regs1,
-				    CSI2_CTX_IRQENABLE(i), reg);
+				    CSI2_CTX_IRQENABLE(i), mask);
 		else
 			iss_reg_clr(csi2->iss, csi2->regs1,
-				    CSI2_CTX_IRQENABLE(i), reg);
+				    CSI2_CTX_IRQENABLE(i), mask);
 	}
 }
 
@@ -679,8 +678,34 @@ static void csi2_isr_ctx(struct iss_csi2_device *csi2,
 	if (status & CSI2_CTX_IRQ_FS) {
 		struct iss_pipeline *pipe =
 				     to_iss_pipeline(&csi2->subdev.entity);
-		if (pipe->do_propagation)
+		u16 frame;
+		u16 delta;
+
+		frame = iss_reg_read(csi2->iss, csi2->regs1,
+				     CSI2_CTX_CTRL2(ctx->ctxnum))
+		      >> CSI2_CTX_CTRL2_FRAME_SHIFT;
+
+		if (frame == 0) {
+			/* A zero value means that the counter isn't implemented
+			 * by the source. Increment the frame number in software
+			 * in that case.
+			 */
 			atomic_inc(&pipe->frame_number);
+		} else {
+			/* Extend the 16 bit frame number to 32 bits by
+			 * computing the delta between two consecutive CSI2
+			 * frame numbers and adding it to the software frame
+			 * number. The hardware counter starts at 1 and wraps
+			 * from 0xffff to 1 without going through 0, so subtract
+			 * 1 when the counter wraps.
+			 */
+			delta = frame - ctx->frame;
+			if (frame < ctx->frame)
+				delta--;
+			ctx->frame = frame;
+
+			atomic_add(delta, &pipe->frame_number);
+		}
 	}
 
 	if (!(status & CSI2_CTX_IRQ_FE))
@@ -1039,7 +1064,6 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
 	struct iss_device *iss = csi2->iss;
-	struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
 	struct iss_video *video_out = &csi2->video_out;
 	int ret = 0;
 
@@ -1058,7 +1082,6 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
 
 		if (omap4iss_csiphy_acquire(csi2->phy) < 0)
 			return -ENODEV;
-		csi2->use_fs_irq = pipe->do_propagation;
 		csi2_configure(csi2);
 		csi2_print_status(csi2);
 
diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h
index 971aa7b08013..3b37978a3bdf 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.h
+++ b/drivers/staging/media/omap4iss/iss_csi2.h
@@ -82,6 +82,7 @@ struct iss_csi2_ctx_cfg {
 	u8 virtual_id;
 	u16 format_id;		/* as in CSI2_CTx_CTRL2[9:0] */
 	u8 dpcm_predictor;	/* 1: simple, 0: advanced */
+	u16 frame;
 
 	/* Fields in CSI2_CTx_CTRL1/3 - Shadowed */
 	u16 alpha;
@@ -137,7 +138,6 @@ struct iss_csi2_device {
 	u32 output; /* output to IPIPEIF, memory or both? */
 	bool dpcm_decompress;
 	unsigned int frame_skip;
-	bool use_fs_irq;
 
 	struct iss_csiphy *phy;
 	struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1];
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
index 32a748398ced..3943fae699ee 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.c
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
@@ -242,23 +242,6 @@ static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif)
 }
 
 /*
- * ipipeif_isif0_isr - Handle ISIF0 event
- * @ipipeif: Pointer to ISP IPIPEIF device.
- *
- * Executes LSC deferred enablement before next frame starts.
- */
-static void ipipeif_isif0_isr(struct iss_ipipeif_device *ipipeif)
-{
-	struct iss_pipeline *pipe =
-			     to_iss_pipeline(&ipipeif->subdev.entity);
-	if (pipe->do_propagation)
-		atomic_inc(&pipe->frame_number);
-
-	if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
-		ipipeif_isr_buffer(ipipeif);
-}
-
-/*
  * omap4iss_ipipeif_isr - Configure ipipeif during interframe time.
  * @ipipeif: Pointer to ISP IPIPEIF device.
  * @events: IPIPEIF events
@@ -269,8 +252,9 @@ void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events)
 					     &ipipeif->stopping))
 		return;
 
-	if (events & ISP5_IRQ_ISIF_INT(0))
-		ipipeif_isif0_isr(ipipeif);
+	if ((events & ISP5_IRQ_ISIF_INT(0)) &&
+	    (ipipeif->output & IPIPEIF_OUTPUT_MEMORY))
+		ipipeif_isr_buffer(ipipeif);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h
index efd0291a86f7..d2b6b6ae9174 100644
--- a/drivers/staging/media/omap4iss/iss_regs.h
+++ b/drivers/staging/media/omap4iss/iss_regs.h
@@ -215,6 +215,8 @@
 #define CSI2_CTX_CTRL1_CTX_EN				(1 << 0)
 
 #define CSI2_CTX_CTRL2(i)				(0x74 + (0x20 * i))
+#define CSI2_CTX_CTRL2_FRAME_MASK			(0xffff << 16)
+#define CSI2_CTX_CTRL2_FRAME_SHIFT			16
 #define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT		13
 #define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK		\
 		(0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
index 88522a8cdf56..3ab972818f1b 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.c
+++ b/drivers/staging/media/omap4iss/iss_resizer.c
@@ -283,22 +283,6 @@ static void resizer_isr_buffer(struct iss_resizer_device *resizer)
 }
 
 /*
- * resizer_isif0_isr - Handle ISIF0 event
- * @resizer: Pointer to ISP RESIZER device.
- *
- * Executes LSC deferred enablement before next frame starts.
- */
-static void resizer_int_dma_isr(struct iss_resizer_device *resizer)
-{
-	struct iss_pipeline *pipe =
-			     to_iss_pipeline(&resizer->subdev.entity);
-	if (pipe->do_propagation)
-		atomic_inc(&pipe->frame_number);
-
-	resizer_isr_buffer(resizer);
-}
-
-/*
  * omap4iss_resizer_isr - Configure resizer during interframe time.
  * @resizer: Pointer to ISP RESIZER device.
  * @events: RESIZER events
@@ -322,7 +306,7 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events)
 		return;
 
 	if (events & ISP5_IRQ_RSZ_INT_DMA)
-		resizer_int_dma_isr(resizer);
+		resizer_isr_buffer(resizer);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index cdee5966cbca..69550445a341 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -25,9 +25,6 @@
 #include "iss_video.h"
 #include "iss.h"
 
-static unsigned debug;
-module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, "activates debug info");
 
 /* -----------------------------------------------------------------------------
  * Helper functions
@@ -773,6 +770,14 @@ iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 }
 
 static int
+iss_video_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *e)
+{
+	struct iss_video_fh *vfh = to_iss_video_fh(fh);
+
+	return vb2_expbuf(&vfh->queue, e);
+}
+
+static int
 iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 {
 	struct iss_video_fh *vfh = to_iss_video_fh(fh);
@@ -1021,6 +1026,7 @@ static const struct v4l2_ioctl_ops iss_video_ioctl_ops = {
 	.vidioc_reqbufs			= iss_video_reqbufs,
 	.vidioc_querybuf		= iss_video_querybuf,
 	.vidioc_qbuf			= iss_video_qbuf,
+	.vidioc_expbuf			= iss_video_expbuf,
 	.vidioc_dqbuf			= iss_video_dqbuf,
 	.vidioc_streamon		= iss_video_streamon,
 	.vidioc_streamoff		= iss_video_streamoff,
@@ -1044,8 +1050,6 @@ static int iss_video_open(struct file *file)
 	if (handle == NULL)
 		return -ENOMEM;
 
-	video->video.debug = debug;
-
 	v4l2_fh_init(&handle->vfh, &video->video);
 	v4l2_fh_add(&handle->vfh);
 
@@ -1071,7 +1075,7 @@ static int iss_video_open(struct file *file)
 	q = &handle->queue;
 
 	q->type = video->type;
-	q->io_modes = VB2_MMAP;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
 	q->drv_priv = handle;
 	q->ops = &iss_video_vb2ops;
 	q->mem_ops = &vb2_dma_contig_memops;
diff --git a/drivers/staging/media/parport/Kconfig b/drivers/staging/media/parport/Kconfig
deleted file mode 100644
index 15974efdba1d..000000000000
--- a/drivers/staging/media/parport/Kconfig
+++ /dev/null
@@ -1,69 +0,0 @@
-menuconfig MEDIA_PARPORT_SUPPORT
-	bool "ISA and parallel port devices"
-	depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT
-	help
-	  Enables drivers for ISA and parallel port bus. If you
-	  need media drivers using those legacy buses, say Y.
-
-if MEDIA_PARPORT_SUPPORT
-config VIDEO_BWQCAM
-	tristate "Quickcam BW Video For Linux (Deprecated)"
-	depends on PARPORT && VIDEO_V4L2
-	select VIDEOBUF2_VMALLOC
-	help
-	  Say Y have if you the black and white version of the QuickCam
-	  camera. See the next option for the color version.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called bw-qcam.
-
-config VIDEO_CQCAM
-	tristate "QuickCam Colour Video For Linux (Deprecated)"
-	depends on PARPORT && VIDEO_V4L2
-	help
-	  This is the video4linux driver for the colour version of the
-	  Connectix QuickCam.  If you have one of these cameras, say Y here,
-	  otherwise say N.  This driver does not work with the original
-	  monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
-	  as a module (c-qcam).
-	  Read <file:Documentation/video4linux/CQcam.txt> for more information.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-
-config VIDEO_PMS
-	tristate "Mediavision Pro Movie Studio Video For Linux (Deprecated)"
-	depends on ISA && VIDEO_V4L2
-	help
-	  Say Y if you have the ISA Mediavision Pro Movie Studio
-	  capture card.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pms.
-
-config VIDEO_W9966
-	tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux (Deprecated)"
-	depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
-	help
-	  Video4linux driver for Winbond's w9966 based Webcams.
-	  Currently tested with the LifeView FlyCam Supra.
-	  If you have one of these cameras, say Y here
-	  otherwise say N.
-	  This driver is also available as a module (w9966).
-
-	  Check out <file:Documentation/video4linux/w9966.txt> for more
-	  information.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-endif
diff --git a/drivers/staging/media/parport/Makefile b/drivers/staging/media/parport/Makefile
deleted file mode 100644
index 4eea06d7af5b..000000000000
--- a/drivers/staging/media/parport/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
-obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
-obj-$(CONFIG_VIDEO_W9966) += w9966.o
-obj-$(CONFIG_VIDEO_PMS) += pms.o
diff --git a/drivers/staging/media/parport/bw-qcam.c b/drivers/staging/media/parport/bw-qcam.c
deleted file mode 100644
index 67b9da1dc43f..000000000000
--- a/drivers/staging/media/parport/bw-qcam.c
+++ /dev/null
@@ -1,1177 +0,0 @@
-/*
- *    QuickCam Driver For Video4Linux.
- *
- *	Video4Linux conversion work by Alan Cox.
- *	Parport compatibility by Phil Blundell.
- *	Busy loop avoidance by Mark Cooke.
- *
- *    Module parameters:
- *
- *	maxpoll=<1 - 5000>
- *
- *	  When polling the QuickCam for a response, busy-wait for a
- *	  maximum of this many loops. The default of 250 gives little
- *	  impact on interactive response.
- *
- *	  NOTE: If this parameter is set too high, the processor
- *		will busy wait until this loop times out, and then
- *		slowly poll for a further 5 seconds before failing
- *		the transaction. You have been warned.
- *
- *	yieldlines=<1 - 250>
- *
- *	  When acquiring a frame from the camera, the data gathering
- *	  loop will yield back to the scheduler after completing
- *	  this many lines. The default of 4 provides a trade-off
- *	  between increased frame acquisition time and impact on
- *	  interactive response.
- */
-
-/* qcam-lib.c -- Library for programming with the Connectix QuickCam.
- * See the included documentation for usage instructions and details
- * of the protocol involved. */
-
-
-/* Version 0.5, August 4, 1996 */
-/* Version 0.7, August 27, 1996 */
-/* Version 0.9, November 17, 1996 */
-
-
-/******************************************************************
-
-Copyright (C) 1996 by Scott Laird
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-******************************************************************/
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/parport.h>
-#include <linux/sched.h>
-#include <linux/videodev2.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-
-/* One from column A... */
-#define QC_NOTSET 0
-#define QC_UNIDIR 1
-#define QC_BIDIR  2
-#define QC_SERIAL 3
-
-/* ... and one from column B */
-#define QC_ANY          0x00
-#define QC_FORCE_UNIDIR 0x10
-#define QC_FORCE_BIDIR  0x20
-#define QC_FORCE_SERIAL 0x30
-/* in the port_mode member */
-
-#define QC_MODE_MASK    0x07
-#define QC_FORCE_MASK   0x70
-
-#define MAX_HEIGHT 243
-#define MAX_WIDTH 336
-
-/* Bit fields for status flags */
-#define QC_PARAM_CHANGE	0x01 /* Camera status change has occurred */
-
-struct qcam {
-	struct v4l2_device v4l2_dev;
-	struct video_device vdev;
-	struct v4l2_ctrl_handler hdl;
-	struct vb2_queue vb_vidq;
-	struct pardevice *pdev;
-	struct parport *pport;
-	struct mutex lock;
-	struct mutex queue_lock;
-	int width, height;
-	int bpp;
-	int mode;
-	int contrast, brightness, whitebal;
-	int port_mode;
-	int transfer_scale;
-	int top, left;
-	int status;
-	unsigned int saved_bits;
-	unsigned long in_use;
-};
-
-static unsigned int maxpoll = 250;   /* Maximum busy-loop count for qcam I/O */
-static unsigned int yieldlines = 4;  /* Yield after this many during capture */
-static int video_nr = -1;
-static unsigned int force_init;		/* Whether to probe aggressively */
-
-module_param(maxpoll, int, 0);
-module_param(yieldlines, int, 0);
-module_param(video_nr, int, 0);
-
-/* Set force_init=1 to avoid detection by polling status register and
- * immediately attempt to initialize qcam */
-module_param(force_init, int, 0);
-
-#define MAX_CAMS 4
-static struct qcam *qcams[MAX_CAMS];
-static unsigned int num_cams;
-
-static inline int read_lpstatus(struct qcam *q)
-{
-	return parport_read_status(q->pport);
-}
-
-static inline int read_lpdata(struct qcam *q)
-{
-	return parport_read_data(q->pport);
-}
-
-static inline void write_lpdata(struct qcam *q, int d)
-{
-	parport_write_data(q->pport, d);
-}
-
-static void write_lpcontrol(struct qcam *q, int d)
-{
-	if (d & 0x20) {
-		/* Set bidirectional mode to reverse (data in) */
-		parport_data_reverse(q->pport);
-	} else {
-		/* Set bidirectional mode to forward (data out) */
-		parport_data_forward(q->pport);
-	}
-
-	/* Now issue the regular port command, but strip out the
-	 * direction flag */
-	d &= ~0x20;
-	parport_write_control(q->pport, d);
-}
-
-
-/* qc_waithand busy-waits for a handshake signal from the QuickCam.
- * Almost all communication with the camera requires handshaking. */
-
-static int qc_waithand(struct qcam *q, int val)
-{
-	int status;
-	int runs = 0;
-
-	if (val) {
-		while (!((status = read_lpstatus(q)) & 8)) {
-			/* 1000 is enough spins on the I/O for all normal
-			   cases, at that point we start to poll slowly
-			   until the camera wakes up. However, we are
-			   busy blocked until the camera responds, so
-			   setting it lower is much better for interactive
-			   response. */
-
-			if (runs++ > maxpoll)
-				msleep_interruptible(5);
-			if (runs > (maxpoll + 1000)) /* 5 seconds */
-				return -1;
-		}
-	} else {
-		while (((status = read_lpstatus(q)) & 8)) {
-			/* 1000 is enough spins on the I/O for all normal
-			   cases, at that point we start to poll slowly
-			   until the camera wakes up. However, we are
-			   busy blocked until the camera responds, so
-			   setting it lower is much better for interactive
-			   response. */
-
-			if (runs++ > maxpoll)
-				msleep_interruptible(5);
-			if (runs++ > (maxpoll + 1000)) /* 5 seconds */
-				return -1;
-		}
-	}
-
-	return status;
-}
-
-/* Waithand2 is used when the qcam is in bidirectional mode, and the
- * handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1
- * (bit 3 of status register).  It also returns the last value read,
- * since this data is useful. */
-
-static unsigned int qc_waithand2(struct qcam *q, int val)
-{
-	unsigned int status;
-	int runs = 0;
-
-	do {
-		status = read_lpdata(q);
-		/* 1000 is enough spins on the I/O for all normal
-		   cases, at that point we start to poll slowly
-		   until the camera wakes up. However, we are
-		   busy blocked until the camera responds, so
-		   setting it lower is much better for interactive
-		   response. */
-
-		if (runs++ > maxpoll)
-			msleep_interruptible(5);
-		if (runs++ > (maxpoll + 1000)) /* 5 seconds */
-			return 0;
-	} while ((status & 1) != val);
-
-	return status;
-}
-
-/* qc_command is probably a bit of a misnomer -- it's used to send
- * bytes *to* the camera.  Generally, these bytes are either commands
- * or arguments to commands, so the name fits, but it still bugs me a
- * bit.  See the documentation for a list of commands. */
-
-static int qc_command(struct qcam *q, int command)
-{
-	int n1, n2;
-	int cmd;
-
-	write_lpdata(q, command);
-	write_lpcontrol(q, 6);
-
-	n1 = qc_waithand(q, 1);
-
-	write_lpcontrol(q, 0xe);
-	n2 = qc_waithand(q, 0);
-
-	cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
-	return cmd;
-}
-
-static int qc_readparam(struct qcam *q)
-{
-	int n1, n2;
-	int cmd;
-
-	write_lpcontrol(q, 6);
-	n1 = qc_waithand(q, 1);
-
-	write_lpcontrol(q, 0xe);
-	n2 = qc_waithand(q, 0);
-
-	cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
-	return cmd;
-}
-
-
-/* Try to detect a QuickCam.  It appears to flash the upper 4 bits of
-   the status register at 5-10 Hz.  This is only used in the autoprobe
-   code.  Be aware that this isn't the way Connectix detects the
-   camera (they send a reset and try to handshake), but this should be
-   almost completely safe, while their method screws up my printer if
-   I plug it in before the camera. */
-
-static int qc_detect(struct qcam *q)
-{
-	int reg, lastreg;
-	int count = 0;
-	int i;
-
-	if (force_init)
-		return 1;
-
-	lastreg = reg = read_lpstatus(q) & 0xf0;
-
-	for (i = 0; i < 500; i++) {
-		reg = read_lpstatus(q) & 0xf0;
-		if (reg != lastreg)
-			count++;
-		lastreg = reg;
-		mdelay(2);
-	}
-
-
-#if 0
-	/* Force camera detection during testing. Sometimes the camera
-	   won't be flashing these bits. Possibly unloading the module
-	   in the middle of a grab? Or some timeout condition?
-	   I've seen this parameter as low as 19 on my 450Mhz box - mpc */
-	printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
-	return 1;
-#endif
-
-	/* Be (even more) liberal in what you accept...  */
-
-	if (count > 20 && count < 400) {
-		return 1;	/* found */
-	} else {
-		printk(KERN_ERR "No Quickcam found on port %s\n",
-				q->pport->name);
-		printk(KERN_DEBUG "Quickcam detection counter: %u\n", count);
-		return 0;	/* not found */
-	}
-}
-
-/* Decide which scan mode to use.  There's no real requirement that
- * the scanmode match the resolution in q->height and q-> width -- the
- * camera takes the picture at the resolution specified in the
- * "scanmode" and then returns the image at the resolution specified
- * with the resolution commands.  If the scan is bigger than the
- * requested resolution, the upper-left hand corner of the scan is
- * returned.  If the scan is smaller, then the rest of the image
- * returned contains garbage. */
-
-static int qc_setscanmode(struct qcam *q)
-{
-	int old_mode = q->mode;
-
-	switch (q->transfer_scale) {
-	case 1:
-		q->mode = 0;
-		break;
-	case 2:
-		q->mode = 4;
-		break;
-	case 4:
-		q->mode = 8;
-		break;
-	}
-
-	switch (q->bpp) {
-	case 4:
-		break;
-	case 6:
-		q->mode += 2;
-		break;
-	}
-
-	switch (q->port_mode & QC_MODE_MASK) {
-	case QC_BIDIR:
-		q->mode += 1;
-		break;
-	case QC_NOTSET:
-	case QC_UNIDIR:
-		break;
-	}
-
-	if (q->mode != old_mode)
-		q->status |= QC_PARAM_CHANGE;
-
-	return 0;
-}
-
-
-/* Reset the QuickCam.  This uses the same sequence the Windows
- * QuickPic program uses.  Someone with a bi-directional port should
- * check that bi-directional mode is detected right, and then
- * implement bi-directional mode in qc_readbyte(). */
-
-static void qc_reset(struct qcam *q)
-{
-	switch (q->port_mode & QC_FORCE_MASK) {
-	case QC_FORCE_UNIDIR:
-		q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
-		break;
-
-	case QC_FORCE_BIDIR:
-		q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
-		break;
-
-	case QC_ANY:
-		write_lpcontrol(q, 0x20);
-		write_lpdata(q, 0x75);
-
-		if (read_lpdata(q) != 0x75)
-			q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
-		else
-			q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
-		break;
-	}
-
-	write_lpcontrol(q, 0xb);
-	udelay(250);
-	write_lpcontrol(q, 0xe);
-	qc_setscanmode(q);		/* in case port_mode changed */
-}
-
-
-
-/* Reset the QuickCam and program for brightness, contrast,
- * white-balance, and resolution. */
-
-static void qc_set(struct qcam *q)
-{
-	int val;
-	int val2;
-
-	/* Set the brightness.  Yes, this is repetitive, but it works.
-	 * Shorter versions seem to fail subtly.  Feel free to try :-). */
-	/* I think the problem was in qc_command, not here -- bls */
-
-	qc_command(q, 0xb);
-	qc_command(q, q->brightness);
-
-	val = q->height / q->transfer_scale;
-	qc_command(q, 0x11);
-	qc_command(q, val);
-	if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) {
-		/* The normal "transfers per line" calculation doesn't seem to work
-		   as expected here (and yet it works fine in qc_scan).  No idea
-		   why this case is the odd man out.  Fortunately, Laird's original
-		   working version gives me a good way to guess at working values.
-		   -- bls */
-		val = q->width;
-		val2 = q->transfer_scale * 4;
-	} else {
-		val = q->width * q->bpp;
-		val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
-			q->transfer_scale;
-	}
-	val = DIV_ROUND_UP(val, val2);
-	qc_command(q, 0x13);
-	qc_command(q, val);
-
-	/* Setting top and left -- bls */
-	qc_command(q, 0xd);
-	qc_command(q, q->top);
-	qc_command(q, 0xf);
-	qc_command(q, q->left / 2);
-
-	qc_command(q, 0x19);
-	qc_command(q, q->contrast);
-	qc_command(q, 0x1f);
-	qc_command(q, q->whitebal);
-
-	/* Clear flag that we must update the grabbing parameters on the camera
-	   before we grab the next frame */
-	q->status &= (~QC_PARAM_CHANGE);
-}
-
-/* Qc_readbytes reads some bytes from the QC and puts them in
-   the supplied buffer.  It returns the number of bytes read,
-   or -1 on error. */
-
-static inline int qc_readbytes(struct qcam *q, char buffer[])
-{
-	int ret = 1;
-	unsigned int hi, lo;
-	unsigned int hi2, lo2;
-	static int state;
-
-	if (buffer == NULL) {
-		state = 0;
-		return 0;
-	}
-
-	switch (q->port_mode & QC_MODE_MASK) {
-	case QC_BIDIR:		/* Bi-directional Port */
-		write_lpcontrol(q, 0x26);
-		lo = (qc_waithand2(q, 1) >> 1);
-		hi = (read_lpstatus(q) >> 3) & 0x1f;
-		write_lpcontrol(q, 0x2e);
-		lo2 = (qc_waithand2(q, 0) >> 1);
-		hi2 = (read_lpstatus(q) >> 3) & 0x1f;
-		switch (q->bpp) {
-		case 4:
-			buffer[0] = lo & 0xf;
-			buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3);
-			buffer[2] = (hi & 0x1e) >> 1;
-			buffer[3] = lo2 & 0xf;
-			buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3);
-			buffer[5] = (hi2 & 0x1e) >> 1;
-			ret = 6;
-			break;
-		case 6:
-			buffer[0] = lo & 0x3f;
-			buffer[1] = ((lo & 0x40) >> 6) | (hi << 1);
-			buffer[2] = lo2 & 0x3f;
-			buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1);
-			ret = 4;
-			break;
-		}
-		break;
-
-	case QC_UNIDIR:	/* Unidirectional Port */
-		write_lpcontrol(q, 6);
-		lo = (qc_waithand(q, 1) & 0xf0) >> 4;
-		write_lpcontrol(q, 0xe);
-		hi = (qc_waithand(q, 0) & 0xf0) >> 4;
-
-		switch (q->bpp) {
-		case 4:
-			buffer[0] = lo;
-			buffer[1] = hi;
-			ret = 2;
-			break;
-		case 6:
-			switch (state) {
-			case 0:
-				buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
-				q->saved_bits = (hi & 3) << 4;
-				state = 1;
-				ret = 1;
-				break;
-			case 1:
-				buffer[0] = lo | q->saved_bits;
-				q->saved_bits = hi << 2;
-				state = 2;
-				ret = 1;
-				break;
-			case 2:
-				buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits;
-				buffer[1] = ((lo & 3) << 4) | hi;
-				state = 0;
-				ret = 2;
-				break;
-			}
-			break;
-		}
-		break;
-	}
-	return ret;
-}
-
-/* requests a scan from the camera.  It sends the correct instructions
- * to the camera and then reads back the correct number of bytes.  In
- * previous versions of this routine the return structure contained
- * the raw output from the camera, and there was a 'qc_convertscan'
- * function that converted that to a useful format.  In version 0.3 I
- * rolled qc_convertscan into qc_scan and now I only return the
- * converted scan.  The format is just an one-dimensional array of
- * characters, one for each pixel, with 0=black up to n=white, where
- * n=2^(bit depth)-1.  Ask me for more details if you don't understand
- * this. */
-
-static long qc_capture(struct qcam *q, u8 *buf, unsigned long len)
-{
-	int i, j, k, yield;
-	int bytes;
-	int linestotrans, transperline;
-	int divisor;
-	int pixels_per_line;
-	int pixels_read = 0;
-	int got = 0;
-	char buffer[6];
-	int  shift = 8 - q->bpp;
-	char invert;
-
-	if (q->mode == -1)
-		return -ENXIO;
-
-	qc_command(q, 0x7);
-	qc_command(q, q->mode);
-
-	if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
-		write_lpcontrol(q, 0x2e);	/* turn port around */
-		write_lpcontrol(q, 0x26);
-		qc_waithand(q, 1);
-		write_lpcontrol(q, 0x2e);
-		qc_waithand(q, 0);
-	}
-
-	/* strange -- should be 15:63 below, but 4bpp is odd */
-	invert = (q->bpp == 4) ? 16 : 63;
-
-	linestotrans = q->height / q->transfer_scale;
-	pixels_per_line = q->width / q->transfer_scale;
-	transperline = q->width * q->bpp;
-	divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
-		q->transfer_scale;
-	transperline = DIV_ROUND_UP(transperline, divisor);
-
-	for (i = 0, yield = yieldlines; i < linestotrans; i++) {
-		for (pixels_read = j = 0; j < transperline; j++) {
-			bytes = qc_readbytes(q, buffer);
-			for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) {
-				int o;
-				if (buffer[k] == 0 && invert == 16) {
-					/* 4bpp is odd (again) -- inverter is 16, not 15, but output
-					   must be 0-15 -- bls */
-					buffer[k] = 16;
-				}
-				o = i * pixels_per_line + pixels_read + k;
-				if (o < len) {
-					u8 ch = invert - buffer[k];
-					got++;
-					buf[o] = ch << shift;
-				}
-			}
-			pixels_read += bytes;
-		}
-		qc_readbytes(q, NULL);	/* reset state machine */
-
-		/* Grabbing an entire frame from the quickcam is a lengthy
-		   process. We don't (usually) want to busy-block the
-		   processor for the entire frame. yieldlines is a module
-		   parameter. If we yield every line, the minimum frame
-		   time will be 240 / 200 = 1.2 seconds. The compile-time
-		   default is to yield every 4 lines. */
-		if (i >= yield) {
-			msleep_interruptible(5);
-			yield = i + yieldlines;
-		}
-	}
-
-	if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
-		write_lpcontrol(q, 2);
-		write_lpcontrol(q, 6);
-		udelay(3);
-		write_lpcontrol(q, 0xe);
-	}
-	if (got < len)
-		return got;
-	return len;
-}
-
-/* ------------------------------------------------------------------
-	Videobuf operations
-   ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
-				unsigned int *nbuffers, unsigned int *nplanes,
-				unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct qcam *dev = vb2_get_drv_priv(vq);
-
-	if (0 == *nbuffers)
-		*nbuffers = 3;
-	*nplanes = 1;
-	mutex_lock(&dev->lock);
-	if (fmt)
-		sizes[0] = fmt->fmt.pix.width * fmt->fmt.pix.height;
-	else
-		sizes[0] = (dev->width / dev->transfer_scale) *
-		   (dev->height / dev->transfer_scale);
-	mutex_unlock(&dev->lock);
-	return 0;
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
-	vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-}
-
-static void buffer_finish(struct vb2_buffer *vb)
-{
-	struct qcam *qcam = vb2_get_drv_priv(vb->vb2_queue);
-	void *vbuf = vb2_plane_vaddr(vb, 0);
-	int size = vb->vb2_queue->plane_sizes[0];
-	int len;
-
-	if (!vb2_is_streaming(vb->vb2_queue))
-		return;
-
-	mutex_lock(&qcam->lock);
-	parport_claim_or_block(qcam->pdev);
-
-	qc_reset(qcam);
-
-	/* Update the camera parameters if we need to */
-	if (qcam->status & QC_PARAM_CHANGE)
-		qc_set(qcam);
-
-	len = qc_capture(qcam, vbuf, size);
-
-	parport_release(qcam->pdev);
-	mutex_unlock(&qcam->lock);
-	v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
-	if (len != size)
-		vb->state = VB2_BUF_STATE_ERROR;
-	vb2_set_plane_payload(vb, 0, len);
-}
-
-static struct vb2_ops qcam_video_qops = {
-	.queue_setup		= queue_setup,
-	.buf_queue		= buffer_queue,
-	.buf_finish		= buffer_finish,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
-};
-
-/*
- *	Video4linux interfacing
- */
-
-static int qcam_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *vcap)
-{
-	struct qcam *qcam = video_drvdata(file);
-
-	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
-	strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
-	strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
-	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
-	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
-{
-	if (vin->index > 0)
-		return -EINVAL;
-	strlcpy(vin->name, "Camera", sizeof(vin->name));
-	vin->type = V4L2_INPUT_TYPE_CAMERA;
-	vin->audioset = 0;
-	vin->tuner = 0;
-	vin->std = 0;
-	vin->status = 0;
-	return 0;
-}
-
-static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
-{
-	*inp = 0;
-	return 0;
-}
-
-static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
-{
-	return (inp > 0) ? -EINVAL : 0;
-}
-
-static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct qcam *qcam = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	pix->width = qcam->width / qcam->transfer_scale;
-	pix->height = qcam->height / qcam->transfer_scale;
-	pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = pix->width;
-	pix->sizeimage = pix->width * pix->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	return 0;
-}
-
-static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	if (pix->height <= 60 || pix->width <= 80) {
-		pix->height = 60;
-		pix->width = 80;
-	} else if (pix->height <= 120 || pix->width <= 160) {
-		pix->height = 120;
-		pix->width = 160;
-	} else {
-		pix->height = 240;
-		pix->width = 320;
-	}
-	if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
-	    pix->pixelformat != V4L2_PIX_FMT_Y6)
-		pix->pixelformat = V4L2_PIX_FMT_Y4;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = pix->width;
-	pix->sizeimage = pix->width * pix->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	return 0;
-}
-
-static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct qcam *qcam = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
-
-	if (ret)
-		return ret;
-	if (vb2_is_busy(&qcam->vb_vidq))
-		return -EBUSY;
-	qcam->width = 320;
-	qcam->height = 240;
-	if (pix->height == 60)
-		qcam->transfer_scale = 4;
-	else if (pix->height == 120)
-		qcam->transfer_scale = 2;
-	else
-		qcam->transfer_scale = 1;
-	if (pix->pixelformat == V4L2_PIX_FMT_Y6)
-		qcam->bpp = 6;
-	else
-		qcam->bpp = 4;
-
-	qc_setscanmode(qcam);
-	/* We must update the camera before we grab. We could
-	   just have changed the grab size */
-	qcam->status |= QC_PARAM_CHANGE;
-	return 0;
-}
-
-static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
-{
-	static struct v4l2_fmtdesc formats[] = {
-		{ 0, 0, 0,
-		  "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
-		  { 0, 0, 0, 0 }
-		},
-		{ 1, 0, 0,
-		  "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
-		  { 0, 0, 0, 0 }
-		},
-	};
-	enum v4l2_buf_type type = fmt->type;
-
-	if (fmt->index > 1)
-		return -EINVAL;
-
-	*fmt = formats[fmt->index];
-	fmt->type = type;
-	return 0;
-}
-
-static int qcam_enum_framesizes(struct file *file, void *fh,
-					 struct v4l2_frmsizeenum *fsize)
-{
-	static const struct v4l2_frmsize_discrete sizes[] = {
-		{  80,  60 },
-		{ 160, 120 },
-		{ 320, 240 },
-	};
-
-	if (fsize->index > 2)
-		return -EINVAL;
-	if (fsize->pixel_format != V4L2_PIX_FMT_Y4 &&
-	    fsize->pixel_format != V4L2_PIX_FMT_Y6)
-		return -EINVAL;
-	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-	fsize->discrete = sizes[fsize->index];
-	return 0;
-}
-
-static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct qcam *qcam =
-		container_of(ctrl->handler, struct qcam, hdl);
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		qcam->brightness = ctrl->val;
-		break;
-	case V4L2_CID_CONTRAST:
-		qcam->contrast = ctrl->val;
-		break;
-	case V4L2_CID_GAMMA:
-		qcam->whitebal = ctrl->val;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	if (ret == 0)
-		qcam->status |= QC_PARAM_CHANGE;
-	return ret;
-}
-
-static const struct v4l2_file_operations qcam_fops = {
-	.owner		= THIS_MODULE,
-	.open		= v4l2_fh_open,
-	.release	= vb2_fop_release,
-	.poll		= vb2_fop_poll,
-	.unlocked_ioctl = video_ioctl2,
-	.read		= vb2_fop_read,
-	.mmap		= vb2_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
-	.vidioc_querycap    		    = qcam_querycap,
-	.vidioc_g_input      		    = qcam_g_input,
-	.vidioc_s_input      		    = qcam_s_input,
-	.vidioc_enum_input   		    = qcam_enum_input,
-	.vidioc_enum_fmt_vid_cap 	    = qcam_enum_fmt_vid_cap,
-	.vidioc_enum_framesizes		    = qcam_enum_framesizes,
-	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
-	.vidioc_reqbufs			    = vb2_ioctl_reqbufs,
-	.vidioc_create_bufs		    = vb2_ioctl_create_bufs,
-	.vidioc_prepare_buf		    = vb2_ioctl_prepare_buf,
-	.vidioc_querybuf		    = vb2_ioctl_querybuf,
-	.vidioc_qbuf			    = vb2_ioctl_qbuf,
-	.vidioc_dqbuf			    = vb2_ioctl_dqbuf,
-	.vidioc_streamon		    = vb2_ioctl_streamon,
-	.vidioc_streamoff		    = vb2_ioctl_streamoff,
-	.vidioc_log_status		    = v4l2_ctrl_log_status,
-	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
-};
-
-static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
-	.s_ctrl = qcam_s_ctrl,
-};
-
-/* Initialize the QuickCam driver control structure.  This is where
- * defaults are set for people who don't have a config file.*/
-
-static struct qcam *qcam_init(struct parport *port)
-{
-	struct qcam *qcam;
-	struct v4l2_device *v4l2_dev;
-	struct vb2_queue *q;
-	int err;
-
-	qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
-	if (qcam == NULL)
-		return NULL;
-
-	v4l2_dev = &qcam->v4l2_dev;
-	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%u", num_cams);
-
-	if (v4l2_device_register(port->dev, v4l2_dev) < 0) {
-		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
-		kfree(qcam);
-		return NULL;
-	}
-
-	v4l2_ctrl_handler_init(&qcam->hdl, 3);
-	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
-			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 180);
-	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
-			  V4L2_CID_CONTRAST, 0, 255, 1, 192);
-	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
-			  V4L2_CID_GAMMA, 0, 255, 1, 105);
-	if (qcam->hdl.error) {
-		v4l2_err(v4l2_dev, "couldn't register controls\n");
-		goto exit;
-	}
-
-	mutex_init(&qcam->lock);
-	mutex_init(&qcam->queue_lock);
-
-	/* initialize queue */
-	q = &qcam->vb_vidq;
-	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-	q->drv_priv = qcam;
-	q->ops = &qcam_video_qops;
-	q->mem_ops = &vb2_vmalloc_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	err = vb2_queue_init(q);
-	if (err < 0) {
-		v4l2_err(v4l2_dev, "couldn't init vb2_queue for %s.\n", port->name);
-		goto exit;
-	}
-	qcam->vdev.queue = q;
-	qcam->vdev.queue->lock = &qcam->queue_lock;
-
-	qcam->pport = port;
-	qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL,
-			NULL, 0, NULL);
-	if (qcam->pdev == NULL) {
-		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
-		goto exit;
-	}
-
-	strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
-	qcam->vdev.v4l2_dev = v4l2_dev;
-	qcam->vdev.ctrl_handler = &qcam->hdl;
-	qcam->vdev.fops = &qcam_fops;
-	qcam->vdev.lock = &qcam->lock;
-	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
-	qcam->vdev.release = video_device_release_empty;
-	video_set_drvdata(&qcam->vdev, qcam);
-
-	qcam->port_mode = (QC_ANY | QC_NOTSET);
-	qcam->width = 320;
-	qcam->height = 240;
-	qcam->bpp = 4;
-	qcam->transfer_scale = 2;
-	qcam->contrast = 192;
-	qcam->brightness = 180;
-	qcam->whitebal = 105;
-	qcam->top = 1;
-	qcam->left = 14;
-	qcam->mode = -1;
-	qcam->status = QC_PARAM_CHANGE;
-	return qcam;
-
-exit:
-	v4l2_ctrl_handler_free(&qcam->hdl);
-	kfree(qcam);
-	return NULL;
-}
-
-static int qc_calibrate(struct qcam *q)
-{
-	/*
-	 *	Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
-	 *	The white balance is an individual value for each
-	 *	quickcam.
-	 */
-
-	int value;
-	int count = 0;
-
-	qc_command(q, 27);	/* AutoAdjustOffset */
-	qc_command(q, 0);	/* Dummy Parameter, ignored by the camera */
-
-	/* GetOffset (33) will read 255 until autocalibration */
-	/* is finished. After that, a value of 1-254 will be */
-	/* returned. */
-
-	do {
-		qc_command(q, 33);
-		value = qc_readparam(q);
-		mdelay(1);
-		schedule();
-		count++;
-	} while (value == 0xff && count < 2048);
-
-	q->whitebal = value;
-	return value;
-}
-
-static int init_bwqcam(struct parport *port)
-{
-	struct qcam *qcam;
-
-	if (num_cams == MAX_CAMS) {
-		printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
-		return -ENOSPC;
-	}
-
-	qcam = qcam_init(port);
-	if (qcam == NULL)
-		return -ENODEV;
-
-	parport_claim_or_block(qcam->pdev);
-
-	qc_reset(qcam);
-
-	if (qc_detect(qcam) == 0) {
-		parport_release(qcam->pdev);
-		parport_unregister_device(qcam->pdev);
-		kfree(qcam);
-		return -ENODEV;
-	}
-	qc_calibrate(qcam);
-	v4l2_ctrl_handler_setup(&qcam->hdl);
-
-	parport_release(qcam->pdev);
-
-	v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
-
-	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-		parport_unregister_device(qcam->pdev);
-		kfree(qcam);
-		return -ENODEV;
-	}
-
-	qcams[num_cams++] = qcam;
-
-	return 0;
-}
-
-static void close_bwqcam(struct qcam *qcam)
-{
-	video_unregister_device(&qcam->vdev);
-	v4l2_ctrl_handler_free(&qcam->hdl);
-	parport_unregister_device(qcam->pdev);
-	kfree(qcam);
-}
-
-/* The parport parameter controls which parports will be scanned.
- * Scanning all parports causes some printers to print a garbage page.
- *       -- March 14, 1999  Billy Donahue <billy@escape.com> */
-#ifdef MODULE
-static char *parport[MAX_CAMS] = { NULL, };
-module_param_array(parport, charp, NULL, 0);
-#endif
-
-static int accept_bwqcam(struct parport *port)
-{
-#ifdef MODULE
-	int n;
-
-	if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
-		/* user gave parport parameters */
-		for (n = 0; n < MAX_CAMS && parport[n]; n++) {
-			char *ep;
-			unsigned long r;
-			r = simple_strtoul(parport[n], &ep, 0);
-			if (ep == parport[n]) {
-				printk(KERN_ERR
-					"bw-qcam: bad port specifier \"%s\"\n",
-					parport[n]);
-				continue;
-			}
-			if (r == port->number)
-				return 1;
-		}
-		return 0;
-	}
-#endif
-	return 1;
-}
-
-static void bwqcam_attach(struct parport *port)
-{
-	if (accept_bwqcam(port))
-		init_bwqcam(port);
-}
-
-static void bwqcam_detach(struct parport *port)
-{
-	int i;
-	for (i = 0; i < num_cams; i++) {
-		struct qcam *qcam = qcams[i];
-		if (qcam && qcam->pdev->port == port) {
-			qcams[i] = NULL;
-			close_bwqcam(qcam);
-		}
-	}
-}
-
-static struct parport_driver bwqcam_driver = {
-	.name	= "bw-qcam",
-	.attach	= bwqcam_attach,
-	.detach	= bwqcam_detach,
-};
-
-static void __exit exit_bw_qcams(void)
-{
-	parport_unregister_driver(&bwqcam_driver);
-}
-
-static int __init init_bw_qcams(void)
-{
-#ifdef MODULE
-	/* Do some sanity checks on the module parameters. */
-	if (maxpoll > 5000) {
-		printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n");
-		maxpoll = 5000;
-	}
-
-	if (yieldlines < 1) {
-		printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n");
-		yieldlines = 1;
-	}
-#endif
-	return parport_register_driver(&bwqcam_driver);
-}
-
-module_init(init_bw_qcams);
-module_exit(exit_bw_qcams);
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.3");
diff --git a/drivers/staging/media/parport/c-qcam.c b/drivers/staging/media/parport/c-qcam.c
deleted file mode 100644
index b9010bd3ed3e..000000000000
--- a/drivers/staging/media/parport/c-qcam.c
+++ /dev/null
@@ -1,882 +0,0 @@
-/*
- *	Video4Linux Colour QuickCam driver
- *	Copyright 1997-2000 Philip Blundell <philb@gnu.org>
- *
- *    Module parameters:
- *
- *	parport=auto      -- probe all parports (default)
- *	parport=0         -- parport0 becomes qcam1
- *	parport=2,0,1     -- parports 2,0,1 are tried in that order
- *
- *	probe=0		  -- do no probing, assume camera is present
- *	probe=1		  -- use IEEE-1284 autoprobe data only (default)
- *	probe=2		  -- probe aggressively for cameras
- *
- *	force_rgb=1       -- force data format to RGB (default is BGR)
- *
- * The parport parameter controls which parports will be scanned.
- * Scanning all parports causes some printers to print a garbage page.
- *       -- March 14, 1999  Billy Donahue <billy@escape.com>
- *
- * Fixed data format to BGR, added force_rgb parameter. Added missing
- * parport_unregister_driver() on module removal.
- *       -- May 28, 2000  Claudio Matsuoka <claudio@conectiva.com>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/parport.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-#include <linux/jiffies.h>
-#include <linux/videodev2.h>
-#include <asm/uaccess.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-
-struct qcam {
-	struct v4l2_device v4l2_dev;
-	struct video_device vdev;
-	struct v4l2_ctrl_handler hdl;
-	struct pardevice *pdev;
-	struct parport *pport;
-	int width, height;
-	int ccd_width, ccd_height;
-	int mode;
-	int contrast, brightness, whitebal;
-	int top, left;
-	unsigned int bidirectional;
-	struct mutex lock;
-};
-
-/* cameras maximum */
-#define MAX_CAMS 4
-
-/* The three possible QuickCam modes */
-#define QC_MILLIONS	0x18
-#define QC_BILLIONS	0x10
-#define QC_THOUSANDS	0x08	/* with VIDEC compression (not supported) */
-
-/* The three possible decimations */
-#define QC_DECIMATION_1		0
-#define QC_DECIMATION_2		2
-#define QC_DECIMATION_4		4
-
-#define BANNER "Colour QuickCam for Video4Linux v0.06"
-
-static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
-static int probe = 2;
-static bool force_rgb;
-static int video_nr = -1;
-
-/* FIXME: parport=auto would never have worked, surely? --RR */
-MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
-			  "probe=<0|1|2> for camera detection method\n"
-			  "force_rgb=<0|1> for RGB data format (default BGR)");
-module_param_array(parport, int, NULL, 0);
-module_param(probe, int, 0);
-module_param(force_rgb, bool, 0);
-module_param(video_nr, int, 0);
-
-static struct qcam *qcams[MAX_CAMS];
-static unsigned int num_cams;
-
-static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
-{
-	/* note: the QC specs refer to the PCAck pin by voltage, not
-	   software level.  PC ports have builtin inverters. */
-	parport_frob_control(qcam->pport, 8, i ? 8 : 0);
-}
-
-static inline unsigned int qcam_ready1(struct qcam *qcam)
-{
-	return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
-}
-
-static inline unsigned int qcam_ready2(struct qcam *qcam)
-{
-	return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
-}
-
-static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
-{
-	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
-	unsigned long oldjiffies = jiffies;
-	unsigned int i;
-
-	for (oldjiffies = jiffies;
-	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
-		if (qcam_ready1(qcam) == value)
-			return 0;
-
-	/* If the camera didn't respond within 1/25 second, poll slowly
-	   for a while. */
-	for (i = 0; i < 50; i++) {
-		if (qcam_ready1(qcam) == value)
-			return 0;
-		msleep_interruptible(100);
-	}
-
-	/* Probably somebody pulled the plug out.  Not much we can do. */
-	v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
-	       parport_read_status(qcam->pport),
-	       parport_read_control(qcam->pport));
-	return 1;
-}
-
-static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
-{
-	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
-	unsigned long oldjiffies = jiffies;
-	unsigned int i;
-
-	for (oldjiffies = jiffies;
-	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
-		if (qcam_ready2(qcam) == value)
-			return 0;
-
-	/* If the camera didn't respond within 1/25 second, poll slowly
-	   for a while. */
-	for (i = 0; i < 50; i++) {
-		if (qcam_ready2(qcam) == value)
-			return 0;
-		msleep_interruptible(100);
-	}
-
-	/* Probably somebody pulled the plug out.  Not much we can do. */
-	v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
-	       parport_read_status(qcam->pport),
-	       parport_read_control(qcam->pport),
-	       parport_read_data(qcam->pport));
-	return 1;
-}
-
-static int qcam_read_data(struct qcam *qcam)
-{
-	unsigned int idata;
-
-	qcam_set_ack(qcam, 0);
-	if (qcam_await_ready1(qcam, 1))
-		return -1;
-	idata = parport_read_status(qcam->pport) & 0xf0;
-	qcam_set_ack(qcam, 1);
-	if (qcam_await_ready1(qcam, 0))
-		return -1;
-	idata |= parport_read_status(qcam->pport) >> 4;
-	return idata;
-}
-
-static int qcam_write_data(struct qcam *qcam, unsigned int data)
-{
-	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
-	unsigned int idata;
-
-	parport_write_data(qcam->pport, data);
-	idata = qcam_read_data(qcam);
-	if (data != idata) {
-		v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
-		       idata);
-		return 1;
-	}
-	return 0;
-}
-
-static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
-{
-	if (qcam_write_data(qcam, cmd))
-		return -1;
-	if (qcam_write_data(qcam, data))
-		return -1;
-	return 0;
-}
-
-static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
-{
-	if (qcam_write_data(qcam, cmd))
-		return -1;
-	return qcam_read_data(qcam);
-}
-
-static int qc_detect(struct qcam *qcam)
-{
-	unsigned int stat, ostat, i, count = 0;
-
-	/* The probe routine below is not very reliable.  The IEEE-1284
-	   probe takes precedence. */
-	/* XXX Currently parport provides no way to distinguish between
-	   "the IEEE probe was not done" and "the probe was done, but
-	   no device was found".  Fix this one day. */
-	if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
-	    && qcam->pport->probe_info[0].model
-	    && !strcmp(qcam->pdev->port->probe_info[0].model,
-		       "Color QuickCam 2.0")) {
-		printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
-		return 1;
-	}
-
-	if (probe < 2)
-		return 0;
-
-	parport_write_control(qcam->pport, 0xc);
-
-	/* look for a heartbeat */
-	ostat = stat = parport_read_status(qcam->pport);
-	for (i = 0; i < 250; i++) {
-		mdelay(1);
-		stat = parport_read_status(qcam->pport);
-		if (ostat != stat) {
-			if (++count >= 3)
-				return 1;
-			ostat = stat;
-		}
-	}
-
-	/* Reset the camera and try again */
-	parport_write_control(qcam->pport, 0xc);
-	parport_write_control(qcam->pport, 0x8);
-	mdelay(1);
-	parport_write_control(qcam->pport, 0xc);
-	mdelay(1);
-	count = 0;
-
-	ostat = stat = parport_read_status(qcam->pport);
-	for (i = 0; i < 250; i++) {
-		mdelay(1);
-		stat = parport_read_status(qcam->pport);
-		if (ostat != stat) {
-			if (++count >= 3)
-				return 1;
-			ostat = stat;
-		}
-	}
-
-	/* no (or flatline) camera, give up */
-	return 0;
-}
-
-static void qc_reset(struct qcam *qcam)
-{
-	parport_write_control(qcam->pport, 0xc);
-	parport_write_control(qcam->pport, 0x8);
-	mdelay(1);
-	parport_write_control(qcam->pport, 0xc);
-	mdelay(1);
-}
-
-/* Reset the QuickCam and program for brightness, contrast,
- * white-balance, and resolution. */
-
-static void qc_setup(struct qcam *qcam)
-{
-	qc_reset(qcam);
-
-	/* Set the brightness. */
-	qcam_set(qcam, 11, qcam->brightness);
-
-	/* Set the height and width.  These refer to the actual
-	   CCD area *before* applying the selected decimation.  */
-	qcam_set(qcam, 17, qcam->ccd_height);
-	qcam_set(qcam, 19, qcam->ccd_width / 2);
-
-	/* Set top and left.  */
-	qcam_set(qcam, 0xd, qcam->top);
-	qcam_set(qcam, 0xf, qcam->left);
-
-	/* Set contrast and white balance.  */
-	qcam_set(qcam, 0x19, qcam->contrast);
-	qcam_set(qcam, 0x1f, qcam->whitebal);
-
-	/* Set the speed.  */
-	qcam_set(qcam, 45, 2);
-}
-
-/* Read some bytes from the camera and put them in the buffer.
-   nbytes should be a multiple of 3, because bidirectional mode gives
-   us three bytes at a time.  */
-
-static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
-{
-	unsigned int bytes = 0;
-
-	qcam_set_ack(qcam, 0);
-	if (qcam->bidirectional) {
-		/* It's a bidirectional port */
-		while (bytes < nbytes) {
-			unsigned int lo1, hi1, lo2, hi2;
-			unsigned char r, g, b;
-
-			if (qcam_await_ready2(qcam, 1))
-				return bytes;
-			lo1 = parport_read_data(qcam->pport) >> 1;
-			hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
-			qcam_set_ack(qcam, 1);
-			if (qcam_await_ready2(qcam, 0))
-				return bytes;
-			lo2 = parport_read_data(qcam->pport) >> 1;
-			hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
-			qcam_set_ack(qcam, 0);
-			r = lo1 | ((hi1 & 1) << 7);
-			g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
-			b = lo2 | ((hi2 & 1) << 7);
-			if (force_rgb) {
-				buf[bytes++] = r;
-				buf[bytes++] = g;
-				buf[bytes++] = b;
-			} else {
-				buf[bytes++] = b;
-				buf[bytes++] = g;
-				buf[bytes++] = r;
-			}
-		}
-	} else {
-		/* It's a unidirectional port */
-		int i = 0, n = bytes;
-		unsigned char rgb[3];
-
-		while (bytes < nbytes) {
-			unsigned int hi, lo;
-
-			if (qcam_await_ready1(qcam, 1))
-				return bytes;
-			hi = (parport_read_status(qcam->pport) & 0xf0);
-			qcam_set_ack(qcam, 1);
-			if (qcam_await_ready1(qcam, 0))
-				return bytes;
-			lo = (parport_read_status(qcam->pport) & 0xf0);
-			qcam_set_ack(qcam, 0);
-			/* flip some bits */
-			rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
-			if (i >= 2) {
-get_fragment:
-				if (force_rgb) {
-					buf[n++] = rgb[0];
-					buf[n++] = rgb[1];
-					buf[n++] = rgb[2];
-				} else {
-					buf[n++] = rgb[2];
-					buf[n++] = rgb[1];
-					buf[n++] = rgb[0];
-				}
-			}
-		}
-		if (i) {
-			i = 0;
-			goto get_fragment;
-		}
-	}
-	return bytes;
-}
-
-#define BUFSZ	150
-
-static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
-{
-	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
-	unsigned lines, pixelsperline;
-	unsigned int is_bi_dir = qcam->bidirectional;
-	size_t wantlen, outptr = 0;
-	char tmpbuf[BUFSZ];
-
-	if (!access_ok(VERIFY_WRITE, buf, len))
-		return -EFAULT;
-
-	/* Wait for camera to become ready */
-	for (;;) {
-		int i = qcam_get(qcam, 41);
-
-		if (i == -1) {
-			qc_setup(qcam);
-			return -EIO;
-		}
-		if ((i & 0x80) == 0)
-			break;
-		schedule();
-	}
-
-	if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
-		return -EIO;
-
-	lines = qcam->height;
-	pixelsperline = qcam->width;
-
-	if (is_bi_dir) {
-		/* Turn the port around */
-		parport_data_reverse(qcam->pport);
-		mdelay(3);
-		qcam_set_ack(qcam, 0);
-		if (qcam_await_ready1(qcam, 1)) {
-			qc_setup(qcam);
-			return -EIO;
-		}
-		qcam_set_ack(qcam, 1);
-		if (qcam_await_ready1(qcam, 0)) {
-			qc_setup(qcam);
-			return -EIO;
-		}
-	}
-
-	wantlen = lines * pixelsperline * 24 / 8;
-
-	while (wantlen) {
-		size_t t, s;
-
-		s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
-		t = qcam_read_bytes(qcam, tmpbuf, s);
-		if (outptr < len) {
-			size_t sz = len - outptr;
-
-			if (sz > t)
-				sz = t;
-			if (__copy_to_user(buf + outptr, tmpbuf, sz))
-				break;
-			outptr += sz;
-		}
-		wantlen -= t;
-		if (t < s)
-			break;
-		cond_resched();
-	}
-
-	len = outptr;
-
-	if (wantlen) {
-		v4l2_err(v4l2_dev, "short read.\n");
-		if (is_bi_dir)
-			parport_data_forward(qcam->pport);
-		qc_setup(qcam);
-		return len;
-	}
-
-	if (is_bi_dir) {
-		int l;
-
-		do {
-			l = qcam_read_bytes(qcam, tmpbuf, 3);
-			cond_resched();
-		} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
-		if (force_rgb) {
-			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
-				v4l2_err(v4l2_dev, "bad EOF\n");
-		} else {
-			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
-				v4l2_err(v4l2_dev, "bad EOF\n");
-		}
-		qcam_set_ack(qcam, 0);
-		if (qcam_await_ready1(qcam, 1)) {
-			v4l2_err(v4l2_dev, "no ack after EOF\n");
-			parport_data_forward(qcam->pport);
-			qc_setup(qcam);
-			return len;
-		}
-		parport_data_forward(qcam->pport);
-		mdelay(3);
-		qcam_set_ack(qcam, 1);
-		if (qcam_await_ready1(qcam, 0)) {
-			v4l2_err(v4l2_dev, "no ack to port turnaround\n");
-			qc_setup(qcam);
-			return len;
-		}
-	} else {
-		int l;
-
-		do {
-			l = qcam_read_bytes(qcam, tmpbuf, 1);
-			cond_resched();
-		} while (l && tmpbuf[0] == 0x7e);
-		l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
-		if (force_rgb) {
-			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
-				v4l2_err(v4l2_dev, "bad EOF\n");
-		} else {
-			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
-				v4l2_err(v4l2_dev, "bad EOF\n");
-		}
-	}
-
-	qcam_write_data(qcam, 0);
-	return len;
-}
-
-/*
- *	Video4linux interfacing
- */
-
-static int qcam_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *vcap)
-{
-	struct qcam *qcam = video_drvdata(file);
-
-	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
-	strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
-	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
-	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
-	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
-{
-	if (vin->index > 0)
-		return -EINVAL;
-	strlcpy(vin->name, "Camera", sizeof(vin->name));
-	vin->type = V4L2_INPUT_TYPE_CAMERA;
-	vin->audioset = 0;
-	vin->tuner = 0;
-	vin->std = 0;
-	vin->status = 0;
-	return 0;
-}
-
-static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
-{
-	*inp = 0;
-	return 0;
-}
-
-static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
-{
-	return (inp > 0) ? -EINVAL : 0;
-}
-
-static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct qcam *qcam = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	pix->width = qcam->width;
-	pix->height = qcam->height;
-	pix->pixelformat = V4L2_PIX_FMT_RGB24;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = 3 * qcam->width;
-	pix->sizeimage = 3 * qcam->width * qcam->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	return 0;
-}
-
-static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	if (pix->height < 60 || pix->width < 80) {
-		pix->height = 60;
-		pix->width = 80;
-	} else if (pix->height < 120 || pix->width < 160) {
-		pix->height = 120;
-		pix->width = 160;
-	} else {
-		pix->height = 240;
-		pix->width = 320;
-	}
-	pix->pixelformat = V4L2_PIX_FMT_RGB24;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = 3 * pix->width;
-	pix->sizeimage = 3 * pix->width * pix->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	return 0;
-}
-
-static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct qcam *qcam = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
-
-	if (ret)
-		return ret;
-	switch (pix->height) {
-	case 60:
-		qcam->mode = QC_DECIMATION_4;
-		break;
-	case 120:
-		qcam->mode = QC_DECIMATION_2;
-		break;
-	default:
-		qcam->mode = QC_DECIMATION_1;
-		break;
-	}
-
-	mutex_lock(&qcam->lock);
-	qcam->mode |= QC_MILLIONS;
-	qcam->height = pix->height;
-	qcam->width = pix->width;
-	parport_claim_or_block(qcam->pdev);
-	qc_setup(qcam);
-	parport_release(qcam->pdev);
-	mutex_unlock(&qcam->lock);
-	return 0;
-}
-
-static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
-{
-	static struct v4l2_fmtdesc formats[] = {
-		{ 0, 0, 0,
-		  "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
-		  { 0, 0, 0, 0 }
-		},
-	};
-	enum v4l2_buf_type type = fmt->type;
-
-	if (fmt->index > 0)
-		return -EINVAL;
-
-	*fmt = formats[fmt->index];
-	fmt->type = type;
-	return 0;
-}
-
-static ssize_t qcam_read(struct file *file, char __user *buf,
-			 size_t count, loff_t *ppos)
-{
-	struct qcam *qcam = video_drvdata(file);
-	int len;
-
-	mutex_lock(&qcam->lock);
-	parport_claim_or_block(qcam->pdev);
-	/* Probably should have a semaphore against multiple users */
-	len = qc_capture(qcam, buf, count);
-	parport_release(qcam->pdev);
-	mutex_unlock(&qcam->lock);
-	return len;
-}
-
-static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct qcam *qcam =
-		container_of(ctrl->handler, struct qcam, hdl);
-	int ret = 0;
-
-	mutex_lock(&qcam->lock);
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		qcam->brightness = ctrl->val;
-		break;
-	case V4L2_CID_CONTRAST:
-		qcam->contrast = ctrl->val;
-		break;
-	case V4L2_CID_GAMMA:
-		qcam->whitebal = ctrl->val;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	if (ret == 0) {
-		parport_claim_or_block(qcam->pdev);
-		qc_setup(qcam);
-		parport_release(qcam->pdev);
-	}
-	mutex_unlock(&qcam->lock);
-	return ret;
-}
-
-static const struct v4l2_file_operations qcam_fops = {
-	.owner		= THIS_MODULE,
-	.open		= v4l2_fh_open,
-	.release	= v4l2_fh_release,
-	.poll		= v4l2_ctrl_poll,
-	.unlocked_ioctl	= video_ioctl2,
-	.read		= qcam_read,
-};
-
-static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
-	.vidioc_querycap    		    = qcam_querycap,
-	.vidioc_g_input      		    = qcam_g_input,
-	.vidioc_s_input      		    = qcam_s_input,
-	.vidioc_enum_input   		    = qcam_enum_input,
-	.vidioc_enum_fmt_vid_cap	    = qcam_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
-	.vidioc_log_status		    = v4l2_ctrl_log_status,
-	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
-};
-
-static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
-	.s_ctrl = qcam_s_ctrl,
-};
-
-/* Initialize the QuickCam driver control structure. */
-
-static struct qcam *qcam_init(struct parport *port)
-{
-	struct qcam *qcam;
-	struct v4l2_device *v4l2_dev;
-
-	qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
-	if (qcam == NULL)
-		return NULL;
-
-	v4l2_dev = &qcam->v4l2_dev;
-	strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
-
-	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
-		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
-		kfree(qcam);
-		return NULL;
-	}
-
-	v4l2_ctrl_handler_init(&qcam->hdl, 3);
-	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
-			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 240);
-	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
-			  V4L2_CID_CONTRAST, 0, 255, 1, 192);
-	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
-			  V4L2_CID_GAMMA, 0, 255, 1, 128);
-	if (qcam->hdl.error) {
-		v4l2_err(v4l2_dev, "couldn't register controls\n");
-		v4l2_ctrl_handler_free(&qcam->hdl);
-		kfree(qcam);
-		return NULL;
-	}
-
-	qcam->pport = port;
-	qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
-					  NULL, 0, NULL);
-
-	qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
-
-	if (qcam->pdev == NULL) {
-		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
-		v4l2_ctrl_handler_free(&qcam->hdl);
-		kfree(qcam);
-		return NULL;
-	}
-
-	strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
-	qcam->vdev.v4l2_dev = v4l2_dev;
-	qcam->vdev.fops = &qcam_fops;
-	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
-	qcam->vdev.release = video_device_release_empty;
-	qcam->vdev.ctrl_handler = &qcam->hdl;
-	video_set_drvdata(&qcam->vdev, qcam);
-
-	mutex_init(&qcam->lock);
-	qcam->width = qcam->ccd_width = 320;
-	qcam->height = qcam->ccd_height = 240;
-	qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
-	qcam->contrast = 192;
-	qcam->brightness = 240;
-	qcam->whitebal = 128;
-	qcam->top = 1;
-	qcam->left = 14;
-	return qcam;
-}
-
-static int init_cqcam(struct parport *port)
-{
-	struct qcam *qcam;
-	struct v4l2_device *v4l2_dev;
-
-	if (parport[0] != -1) {
-		/* The user gave specific instructions */
-		int i, found = 0;
-
-		for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
-			if (parport[0] == port->number)
-				found = 1;
-		}
-		if (!found)
-			return -ENODEV;
-	}
-
-	if (num_cams == MAX_CAMS)
-		return -ENOSPC;
-
-	qcam = qcam_init(port);
-	if (qcam == NULL)
-		return -ENODEV;
-
-	v4l2_dev = &qcam->v4l2_dev;
-
-	parport_claim_or_block(qcam->pdev);
-
-	qc_reset(qcam);
-
-	if (probe && qc_detect(qcam) == 0) {
-		parport_release(qcam->pdev);
-		parport_unregister_device(qcam->pdev);
-		kfree(qcam);
-		return -ENODEV;
-	}
-
-	qc_setup(qcam);
-
-	parport_release(qcam->pdev);
-
-	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-		v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
-		       qcam->pport->name);
-		parport_unregister_device(qcam->pdev);
-		kfree(qcam);
-		return -ENODEV;
-	}
-
-	v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
-	       video_device_node_name(&qcam->vdev), qcam->pport->name);
-
-	qcams[num_cams++] = qcam;
-
-	return 0;
-}
-
-static void close_cqcam(struct qcam *qcam)
-{
-	video_unregister_device(&qcam->vdev);
-	v4l2_ctrl_handler_free(&qcam->hdl);
-	parport_unregister_device(qcam->pdev);
-	kfree(qcam);
-}
-
-static void cq_attach(struct parport *port)
-{
-	init_cqcam(port);
-}
-
-static void cq_detach(struct parport *port)
-{
-	/* Write this some day. */
-}
-
-static struct parport_driver cqcam_driver = {
-	.name = "cqcam",
-	.attach = cq_attach,
-	.detach = cq_detach,
-};
-
-static int __init cqcam_init(void)
-{
-	printk(KERN_INFO BANNER "\n");
-
-	return parport_register_driver(&cqcam_driver);
-}
-
-static void __exit cqcam_cleanup(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < num_cams; i++)
-		close_cqcam(qcams[i]);
-
-	parport_unregister_driver(&cqcam_driver);
-}
-
-MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
-MODULE_DESCRIPTION(BANNER);
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.4");
-
-module_init(cqcam_init);
-module_exit(cqcam_cleanup);
diff --git a/drivers/staging/media/parport/pms.c b/drivers/staging/media/parport/pms.c
deleted file mode 100644
index e6b497528cea..000000000000
--- a/drivers/staging/media/parport/pms.c
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- *	Media Vision Pro Movie Studio
- *			or
- *	"all you need is an I2C bus some RAM and a prayer"
- *
- *	This draws heavily on code
- *
- *	(c) Wolfgang Koehler,  wolf@first.gmd.de, Dec. 1994
- *	Kiefernring 15
- *	14478 Potsdam, Germany
- *
- *	Most of this code is directly derived from his userspace driver.
- *	His driver works so send any reports to alan@lxorguk.ukuu.org.uk
- *	unless the userspace driver also doesn't work for you...
- *
- *      Changes:
- *	25-11-2009 	Hans Verkuil <hverkuil@xs4all.nl>
- * 			- converted to version 2 of the V4L API.
- *      08/07/2003      Daniele Bellucci <bellucda@tiscali.it>
- *                      - pms_capture: report back -EFAULT
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/isa.h>
-#include <asm/io.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-device.h>
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.5");
-
-#define MOTOROLA	1
-#define PHILIPS2	2               /* SAA7191 */
-#define PHILIPS1	3
-#define MVVMEMORYWIDTH	0x40		/* 512 bytes */
-
-struct i2c_info {
-	u8 slave;
-	u8 sub;
-	u8 data;
-	u8 hits;
-};
-
-struct pms {
-	struct v4l2_device v4l2_dev;
-	struct video_device vdev;
-	struct v4l2_ctrl_handler hdl;
-	int height;
-	int width;
-	int depth;
-	int input;
-	struct mutex lock;
-	int i2c_count;
-	struct i2c_info i2cinfo[64];
-
-	int decoder;
-	int standard;	/* 0 - auto 1 - ntsc 2 - pal 3 - secam */
-	v4l2_std_id std;
-	int io;
-	int data;
-	void __iomem *mem;
-};
-
-/*
- *	I/O ports and Shared Memory
- */
-
-static int io_port = 0x250;
-module_param(io_port, int, 0);
-
-static int mem_base = 0xc8000;
-module_param(mem_base, int, 0);
-
-static int video_nr = -1;
-module_param(video_nr, int, 0);
-
-
-static inline void mvv_write(struct pms *dev, u8 index, u8 value)
-{
-	outw(index | (value << 8), dev->io);
-}
-
-static inline u8 mvv_read(struct pms *dev, u8 index)
-{
-	outb(index, dev->io);
-	return inb(dev->data);
-}
-
-static int pms_i2c_stat(struct pms *dev, u8 slave)
-{
-	int counter = 0;
-	int i;
-
-	outb(0x28, dev->io);
-
-	while ((inb(dev->data) & 0x01) == 0)
-		if (counter++ == 256)
-			break;
-
-	while ((inb(dev->data) & 0x01) != 0)
-		if (counter++ == 256)
-			break;
-
-	outb(slave, dev->io);
-
-	counter = 0;
-	while ((inb(dev->data) & 0x01) == 0)
-		if (counter++ == 256)
-			break;
-
-	while ((inb(dev->data) & 0x01) != 0)
-		if (counter++ == 256)
-			break;
-
-	for (i = 0; i < 12; i++) {
-		char st = inb(dev->data);
-
-		if ((st & 2) != 0)
-			return -1;
-		if ((st & 1) == 0)
-			break;
-	}
-	outb(0x29, dev->io);
-	return inb(dev->data);
-}
-
-static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
-{
-	int skip = 0;
-	int count;
-	int i;
-
-	for (i = 0; i < dev->i2c_count; i++) {
-		if ((dev->i2cinfo[i].slave == slave) &&
-		    (dev->i2cinfo[i].sub == sub)) {
-			if (dev->i2cinfo[i].data == data)
-				skip = 1;
-			dev->i2cinfo[i].data = data;
-			i = dev->i2c_count + 1;
-		}
-	}
-
-	if (i == dev->i2c_count && dev->i2c_count < 64) {
-		dev->i2cinfo[dev->i2c_count].slave = slave;
-		dev->i2cinfo[dev->i2c_count].sub = sub;
-		dev->i2cinfo[dev->i2c_count].data = data;
-		dev->i2c_count++;
-	}
-
-	if (skip)
-		return 0;
-
-	mvv_write(dev, 0x29, sub);
-	mvv_write(dev, 0x2A, data);
-	mvv_write(dev, 0x28, slave);
-
-	outb(0x28, dev->io);
-
-	count = 0;
-	while ((inb(dev->data) & 1) == 0)
-		if (count > 255)
-			break;
-	while ((inb(dev->data) & 1) != 0)
-		if (count > 255)
-			break;
-
-	count = inb(dev->data);
-
-	if (count & 2)
-		return -1;
-	return count;
-}
-
-static int pms_i2c_read(struct pms *dev, int slave, int sub)
-{
-	int i;
-
-	for (i = 0; i < dev->i2c_count; i++) {
-		if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
-			return dev->i2cinfo[i].data;
-	}
-	return 0;
-}
-
-
-static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
-{
-	u8 tmp;
-
-	tmp = pms_i2c_read(dev, slave, sub);
-	tmp = (tmp & and) | or;
-	pms_i2c_write(dev, slave, sub, tmp);
-}
-
-/*
- *	Control functions
- */
-
-
-static void pms_videosource(struct pms *dev, short source)
-{
-	switch (dev->decoder) {
-	case MOTOROLA:
-		break;
-	case PHILIPS2:
-		pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
-		break;
-	case PHILIPS1:
-		break;
-	}
-	mvv_write(dev, 0x2E, 0x31);
-	/* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
-	   But could not make this work correctly. Only Composite input
-	   worked for me. */
-}
-
-static void pms_hue(struct pms *dev, short hue)
-{
-	switch (dev->decoder) {
-	case MOTOROLA:
-		pms_i2c_write(dev, 0x8a, 0x00, hue);
-		break;
-	case PHILIPS2:
-		pms_i2c_write(dev, 0x8a, 0x07, hue);
-		break;
-	case PHILIPS1:
-		pms_i2c_write(dev, 0x42, 0x07, hue);
-		break;
-	}
-}
-
-static void pms_saturation(struct pms *dev, short sat)
-{
-	switch (dev->decoder) {
-	case MOTOROLA:
-		pms_i2c_write(dev, 0x8a, 0x00, sat);
-		break;
-	case PHILIPS1:
-		pms_i2c_write(dev, 0x42, 0x12, sat);
-		break;
-	}
-}
-
-
-static void pms_contrast(struct pms *dev, short contrast)
-{
-	switch (dev->decoder) {
-	case MOTOROLA:
-		pms_i2c_write(dev, 0x8a, 0x00, contrast);
-		break;
-	case PHILIPS1:
-		pms_i2c_write(dev, 0x42, 0x13, contrast);
-		break;
-	}
-}
-
-static void pms_brightness(struct pms *dev, short brightness)
-{
-	switch (dev->decoder) {
-	case MOTOROLA:
-		pms_i2c_write(dev, 0x8a, 0x00, brightness);
-		pms_i2c_write(dev, 0x8a, 0x00, brightness);
-		pms_i2c_write(dev, 0x8a, 0x00, brightness);
-		break;
-	case PHILIPS1:
-		pms_i2c_write(dev, 0x42, 0x19, brightness);
-		break;
-	}
-}
-
-
-static void pms_format(struct pms *dev, short format)
-{
-	int target;
-
-	dev->standard = format;
-
-	if (dev->decoder == PHILIPS1)
-		target = 0x42;
-	else if (dev->decoder == PHILIPS2)
-		target = 0x8a;
-	else
-		return;
-
-	switch (format) {
-	case 0:	/* Auto */
-		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
-		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
-		break;
-	case 1: /* NTSC */
-		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
-		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
-		break;
-	case 2: /* PAL */
-		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
-		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
-		break;
-	case 3:	/* SECAM */
-		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
-		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
-		break;
-	}
-}
-
-#ifdef FOR_FUTURE_EXPANSION
-
-/*
- *	These features of the PMS card are not currently exposes. They
- *	could become a private v4l ioctl for PMSCONFIG or somesuch if
- *	people need it. We also don't yet use the PMS interrupt.
- */
-
-static void pms_hstart(struct pms *dev, short start)
-{
-	switch (dev->decoder) {
-	case PHILIPS1:
-		pms_i2c_write(dev, 0x8a, 0x05, start);
-		pms_i2c_write(dev, 0x8a, 0x18, start);
-		break;
-	case PHILIPS2:
-		pms_i2c_write(dev, 0x42, 0x05, start);
-		pms_i2c_write(dev, 0x42, 0x18, start);
-		break;
-	}
-}
-
-/*
- *	Bandpass filters
- */
-
-static void pms_bandpass(struct pms *dev, short pass)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
-}
-
-static void pms_antisnow(struct pms *dev, short snow)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
-}
-
-static void pms_sharpness(struct pms *dev, short sharp)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
-}
-
-static void pms_chromaagc(struct pms *dev, short agc)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
-}
-
-static void pms_vertnoise(struct pms *dev, short noise)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
-}
-
-static void pms_forcecolour(struct pms *dev, short colour)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
-}
-
-static void pms_antigamma(struct pms *dev, short gamma)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
-}
-
-static void pms_prefilter(struct pms *dev, short filter)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
-}
-
-static void pms_hfilter(struct pms *dev, short filter)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
-}
-
-static void pms_vfilter(struct pms *dev, short filter)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
-}
-
-static void pms_killcolour(struct pms *dev, short colour)
-{
-	if (dev->decoder == PHILIPS2) {
-		pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
-		pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
-	} else if (dev->decoder == PHILIPS1) {
-		pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
-		pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
-	}
-}
-
-static void pms_chromagain(struct pms *dev, short chroma)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_write(dev, 0x8a, 0x11, chroma);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_write(dev, 0x42, 0x11, chroma);
-}
-
-
-static void pms_spacialcompl(struct pms *dev, short data)
-{
-	mvv_write(dev, 0x3b, data);
-}
-
-static void pms_spacialcomph(struct pms *dev, short data)
-{
-	mvv_write(dev, 0x3a, data);
-}
-
-static void pms_vstart(struct pms *dev, short start)
-{
-	mvv_write(dev, 0x16, start);
-	mvv_write(dev, 0x17, (start >> 8) & 0x01);
-}
-
-#endif
-
-static void pms_secamcross(struct pms *dev, short cross)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
-}
-
-
-static void pms_swsense(struct pms *dev, short sense)
-{
-	if (dev->decoder == PHILIPS2) {
-		pms_i2c_write(dev, 0x8a, 0x0a, sense);
-		pms_i2c_write(dev, 0x8a, 0x0b, sense);
-	} else if (dev->decoder == PHILIPS1) {
-		pms_i2c_write(dev, 0x42, 0x0a, sense);
-		pms_i2c_write(dev, 0x42, 0x0b, sense);
-	}
-}
-
-
-static void pms_framerate(struct pms *dev, short frr)
-{
-	int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
-
-	if (frr == 0)
-		return;
-	fps = fps/frr;
-	mvv_write(dev, 0x14, 0x80 | fps);
-	mvv_write(dev, 0x15, 1);
-}
-
-static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
-{
-	mvv_write(dev, 0x1c, deciden);	/* Denominator */
-	mvv_write(dev, 0x1d, decinum);	/* Numerator */
-}
-
-/*
- *	Turn 16bit ratios into best small ratio the chipset can grok
- */
-
-static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
-{
-	/* Knock it down by / 5 once */
-	if (decinum % 5 == 0) {
-		deciden /= 5;
-		decinum /= 5;
-	}
-	/*
-	 *	3's
-	 */
-	while (decinum % 3 == 0 && deciden % 3 == 0) {
-		deciden /= 3;
-		decinum /= 3;
-	}
-	/*
-	 *	2's
-	 */
-	while (decinum % 2 == 0 && deciden % 2 == 0) {
-		decinum /= 2;
-		deciden /= 2;
-	}
-	/*
-	 *	Fudgyify
-	 */
-	while (deciden > 32) {
-		deciden /= 2;
-		decinum = (decinum + 1) / 2;
-	}
-	if (deciden == 32)
-		deciden--;
-	pms_vert(dev, deciden, decinum);
-}
-
-static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
-{
-	if (decinum <= 512) {
-		if (decinum % 5 == 0) {
-			decinum /= 5;
-			deciden /= 5;
-		}
-	} else {
-		decinum = 512;
-		deciden = 640;	/* 768 would be ideal */
-	}
-
-	while (((decinum | deciden) & 1) == 0) {
-		decinum >>= 1;
-		deciden >>= 1;
-	}
-	while (deciden > 32) {
-		deciden >>= 1;
-		decinum = (decinum + 1) >> 1;
-	}
-	if (deciden == 32)
-		deciden--;
-
-	mvv_write(dev, 0x24, 0x80 | deciden);
-	mvv_write(dev, 0x25, decinum);
-}
-
-static void pms_resolution(struct pms *dev, short width, short height)
-{
-	int fg_height;
-
-	fg_height = height;
-	if (fg_height > 280)
-		fg_height = 280;
-
-	mvv_write(dev, 0x18, fg_height);
-	mvv_write(dev, 0x19, fg_height >> 8);
-
-	if (dev->std & V4L2_STD_525_60) {
-		mvv_write(dev, 0x1a, 0xfc);
-		mvv_write(dev, 0x1b, 0x00);
-		if (height > fg_height)
-			pms_vertdeci(dev, 240, 240);
-		else
-			pms_vertdeci(dev, fg_height, 240);
-	} else {
-		mvv_write(dev, 0x1a, 0x1a);
-		mvv_write(dev, 0x1b, 0x01);
-		if (fg_height > 256)
-			pms_vertdeci(dev, 270, 270);
-		else
-			pms_vertdeci(dev, fg_height, 270);
-	}
-	mvv_write(dev, 0x12, 0);
-	mvv_write(dev, 0x13, MVVMEMORYWIDTH);
-	mvv_write(dev, 0x42, 0x00);
-	mvv_write(dev, 0x43, 0x00);
-	mvv_write(dev, 0x44, MVVMEMORYWIDTH);
-
-	mvv_write(dev, 0x22, width + 8);
-	mvv_write(dev, 0x23, (width + 8) >> 8);
-
-	if (dev->std & V4L2_STD_525_60)
-		pms_horzdeci(dev, width, 640);
-	else
-		pms_horzdeci(dev, width + 8, 768);
-
-	mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
-	mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
-	mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
-	mvv_write(dev, 0x32, 0x00);
-	mvv_write(dev, 0x33, MVVMEMORYWIDTH);
-}
-
-
-/*
- *	Set Input
- */
-
-static void pms_vcrinput(struct pms *dev, short input)
-{
-	if (dev->decoder == PHILIPS2)
-		pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
-	else if (dev->decoder == PHILIPS1)
-		pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
-}
-
-
-static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
-{
-	int y;
-	int dw = 2 * dev->width;
-	char *tmp; /* using a temp buffer is faster than direct  */
-	int cnt = 0;
-	int len = 0;
-	unsigned char r8 = 0x5;  /* value for reg8  */
-
-	tmp = kmalloc(dw + 32, GFP_KERNEL);
-	if (!tmp)
-		return 0;
-
-	if (rgb555)
-		r8 |= 0x20; /* else use untranslated rgb = 565 */
-	mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
-
-/*	printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
-
-	for (y = 0; y < dev->height; y++) {
-		writeb(0, dev->mem);  /* synchronisiert neue Zeile */
-
-		/*
-		 *	This is in truth a fifo, be very careful as if you
-		 *	forgot this odd things will occur 8)
-		 */
-
-		memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word   */
-		cnt -= dev->height;
-		while (cnt <= 0) {
-			/*
-			 *	Don't copy too far
-			 */
-			int dt = dw;
-			if (dt + len > count)
-				dt = count - len;
-			cnt += dev->height;
-			if (copy_to_user(buf, tmp + 32, dt))
-				return len ? len : -EFAULT;
-			buf += dt;
-			len += dt;
-		}
-	}
-	kfree(tmp);
-	return len;
-}
-
-
-/*
- *	Video4linux interfacing
- */
-
-static int pms_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *vcap)
-{
-	struct pms *dev = video_drvdata(file);
-
-	strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
-	strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
-	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
-			"ISA:%s", dev->v4l2_dev.name);
-	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
-	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
-{
-	static const char *inputs[4] = {
-		"Composite",
-		"S-Video",
-		"Composite (VCR)",
-		"S-Video (VCR)"
-	};
-
-	if (vin->index > 3)
-		return -EINVAL;
-	strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
-	vin->type = V4L2_INPUT_TYPE_CAMERA;
-	vin->audioset = 0;
-	vin->tuner = 0;
-	vin->std = V4L2_STD_ALL;
-	vin->status = 0;
-	return 0;
-}
-
-static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
-{
-	struct pms *dev = video_drvdata(file);
-
-	*inp = dev->input;
-	return 0;
-}
-
-static int pms_s_input(struct file *file, void *fh, unsigned int inp)
-{
-	struct pms *dev = video_drvdata(file);
-
-	if (inp > 3)
-		return -EINVAL;
-
-	dev->input = inp;
-	pms_videosource(dev, inp & 1);
-	pms_vcrinput(dev, inp >> 1);
-	return 0;
-}
-
-static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
-{
-	struct pms *dev = video_drvdata(file);
-
-	*std = dev->std;
-	return 0;
-}
-
-static int pms_s_std(struct file *file, void *fh, v4l2_std_id std)
-{
-	struct pms *dev = video_drvdata(file);
-	int ret = 0;
-
-	dev->std = std;
-	if (dev->std & V4L2_STD_NTSC) {
-		pms_framerate(dev, 30);
-		pms_secamcross(dev, 0);
-		pms_format(dev, 1);
-	} else if (dev->std & V4L2_STD_PAL) {
-		pms_framerate(dev, 25);
-		pms_secamcross(dev, 0);
-		pms_format(dev, 2);
-	} else if (dev->std & V4L2_STD_SECAM) {
-		pms_framerate(dev, 25);
-		pms_secamcross(dev, 1);
-		pms_format(dev, 2);
-	} else {
-		ret = -EINVAL;
-	}
-	/*
-	switch (v->mode) {
-	case VIDEO_MODE_AUTO:
-		pms_framerate(dev, 25);
-		pms_secamcross(dev, 0);
-		pms_format(dev, 0);
-		break;
-	}*/
-	return ret;
-}
-
-static int pms_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct pms *dev = container_of(ctrl->handler, struct pms, hdl);
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		pms_brightness(dev, ctrl->val);
-		break;
-	case V4L2_CID_CONTRAST:
-		pms_contrast(dev, ctrl->val);
-		break;
-	case V4L2_CID_SATURATION:
-		pms_saturation(dev, ctrl->val);
-		break;
-	case V4L2_CID_HUE:
-		pms_hue(dev, ctrl->val);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct pms *dev = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	pix->width = dev->width;
-	pix->height = dev->height;
-	pix->pixelformat = dev->width == 15 ?
-			    V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = 2 * dev->width;
-	pix->sizeimage = 2 * dev->width * dev->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	return 0;
-}
-
-static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	if (pix->height < 16 || pix->height > 480)
-		return -EINVAL;
-	if (pix->width < 16 || pix->width > 640)
-		return -EINVAL;
-	if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
-	    pix->pixelformat != V4L2_PIX_FMT_RGB565)
-		return -EINVAL;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = 2 * pix->width;
-	pix->sizeimage = 2 * pix->width * pix->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SRGB;
-	return 0;
-}
-
-static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct pms *dev = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-	int ret = pms_try_fmt_vid_cap(file, fh, fmt);
-
-	if (ret)
-		return ret;
-	dev->width = pix->width;
-	dev->height = pix->height;
-	dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
-	pms_resolution(dev, dev->width, dev->height);
-	/* Ok we figured out what to use from our wide choice */
-	return 0;
-}
-
-static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
-{
-	static struct v4l2_fmtdesc formats[] = {
-		{ 0, 0, 0,
-		  "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
-		  { 0, 0, 0, 0 }
-		},
-		{ 1, 0, 0,
-		  "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
-		  { 0, 0, 0, 0 }
-		},
-	};
-	enum v4l2_buf_type type = fmt->type;
-
-	if (fmt->index > 1)
-		return -EINVAL;
-
-	*fmt = formats[fmt->index];
-	fmt->type = type;
-	return 0;
-}
-
-static ssize_t pms_read(struct file *file, char __user *buf,
-		    size_t count, loff_t *ppos)
-{
-	struct pms *dev = video_drvdata(file);
-	int len;
-
-	len = pms_capture(dev, buf, (dev->depth == 15), count);
-	return len;
-}
-
-static unsigned int pms_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct v4l2_fh *fh = file->private_data;
-	unsigned int res = POLLIN | POLLRDNORM;
-
-	if (v4l2_event_pending(fh))
-		res |= POLLPRI;
-	poll_wait(file, &fh->wait, wait);
-	return res;
-}
-
-static const struct v4l2_file_operations pms_fops = {
-	.owner		= THIS_MODULE,
-	.open           = v4l2_fh_open,
-	.release        = v4l2_fh_release,
-	.poll           = pms_poll,
-	.unlocked_ioctl	= video_ioctl2,
-	.read           = pms_read,
-};
-
-static const struct v4l2_ioctl_ops pms_ioctl_ops = {
-	.vidioc_querycap	    = pms_querycap,
-	.vidioc_g_input		    = pms_g_input,
-	.vidioc_s_input		    = pms_s_input,
-	.vidioc_enum_input	    = pms_enum_input,
-	.vidioc_g_std		    = pms_g_std,
-	.vidioc_s_std		    = pms_s_std,
-	.vidioc_enum_fmt_vid_cap    = pms_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap	    = pms_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap	    = pms_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap     = pms_try_fmt_vid_cap,
-	.vidioc_subscribe_event     = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
-};
-
-/*
- *	Probe for and initialise the Mediavision PMS
- */
-
-static int init_mediavision(struct pms *dev)
-{
-	int idec, decst;
-	int i;
-	static const unsigned char i2c_defs[] = {
-		0x4c, 0x30, 0x00, 0xe8,
-		0xb6, 0xe2, 0x00, 0x00,
-		0xff, 0xff, 0x00, 0x00,
-		0x00, 0x00, 0x78, 0x98,
-		0x00, 0x00, 0x00, 0x00,
-		0x34, 0x0a, 0xf4, 0xce,
-		0xe4
-	};
-
-	dev->mem = ioremap(mem_base, 0x800);
-	if (!dev->mem)
-		return -ENOMEM;
-
-	if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
-		printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
-		iounmap(dev->mem);
-		return -EBUSY;
-	}
-	if (!request_region(dev->io, 3, "Mediavision PMS")) {
-		printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
-		release_region(0x9a01, 1);
-		iounmap(dev->mem);
-		return -EBUSY;
-	}
-	outb(0xb8, 0x9a01);		/* Unlock */
-	outb(dev->io >> 4, 0x9a01);	/* Set IO port */
-
-
-	decst = pms_i2c_stat(dev, 0x43);
-
-	if (decst != -1)
-		idec = 2;
-	else if (pms_i2c_stat(dev, 0xb9) != -1)
-		idec = 3;
-	else if (pms_i2c_stat(dev, 0x8b) != -1)
-		idec = 1;
-	else
-		idec = 0;
-
-	printk(KERN_INFO "PMS type is %d\n", idec);
-	if (idec == 0) {
-		release_region(dev->io, 3);
-		release_region(0x9a01, 1);
-		iounmap(dev->mem);
-		return -ENODEV;
-	}
-
-	/*
-	 *	Ok we have a PMS of some sort
-	 */
-
-	mvv_write(dev, 0x04, mem_base >> 12);	/* Set the memory area */
-
-	/* Ok now load the defaults */
-
-	for (i = 0; i < 0x19; i++) {
-		if (i2c_defs[i] == 0xff)
-			pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
-		else
-			pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
-	}
-
-	pms_i2c_write(dev, 0xb8, 0x00, 0x12);
-	pms_i2c_write(dev, 0xb8, 0x04, 0x00);
-	pms_i2c_write(dev, 0xb8, 0x07, 0x00);
-	pms_i2c_write(dev, 0xb8, 0x08, 0x00);
-	pms_i2c_write(dev, 0xb8, 0x09, 0xff);
-	pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
-	pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
-	pms_i2c_write(dev, 0xb8, 0x10, 0x03);
-
-	mvv_write(dev, 0x01, 0x00);
-	mvv_write(dev, 0x05, 0xa0);
-	mvv_write(dev, 0x08, 0x25);
-	mvv_write(dev, 0x09, 0x00);
-	mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
-
-	mvv_write(dev, 0x10, 0x02);
-	mvv_write(dev, 0x1e, 0x0c);
-	mvv_write(dev, 0x1f, 0x03);
-	mvv_write(dev, 0x26, 0x06);
-
-	mvv_write(dev, 0x2b, 0x00);
-	mvv_write(dev, 0x2c, 0x20);
-	mvv_write(dev, 0x2d, 0x00);
-	mvv_write(dev, 0x2f, 0x70);
-	mvv_write(dev, 0x32, 0x00);
-	mvv_write(dev, 0x33, MVVMEMORYWIDTH);
-	mvv_write(dev, 0x34, 0x00);
-	mvv_write(dev, 0x35, 0x00);
-	mvv_write(dev, 0x3a, 0x80);
-	mvv_write(dev, 0x3b, 0x10);
-	mvv_write(dev, 0x20, 0x00);
-	mvv_write(dev, 0x21, 0x00);
-	mvv_write(dev, 0x30, 0x22);
-	return 0;
-}
-
-/*
- *	Initialization and module stuff
- */
-
-#ifndef MODULE
-static int enable;
-module_param(enable, int, 0);
-#endif
-
-static const struct v4l2_ctrl_ops pms_ctrl_ops = {
-	.s_ctrl = pms_s_ctrl,
-};
-
-static int pms_probe(struct device *pdev, unsigned int card)
-{
-	struct pms *dev;
-	struct v4l2_device *v4l2_dev;
-	struct v4l2_ctrl_handler *hdl;
-	int res;
-
-#ifndef MODULE
-	if (!enable) {
-		pr_err("PMS: not enabled, use pms.enable=1 to probe\n");
-		return -ENODEV;
-	}
-#endif
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL)
-		return -ENOMEM;
-
-	dev->decoder = PHILIPS2;
-	dev->io = io_port;
-	dev->data = io_port + 1;
-	v4l2_dev = &dev->v4l2_dev;
-	hdl = &dev->hdl;
-
-	res = v4l2_device_register(pdev, v4l2_dev);
-	if (res < 0) {
-		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
-		goto free_dev;
-	}
-	v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.05\n");
-
-	res = init_mediavision(dev);
-	if (res) {
-		v4l2_err(v4l2_dev, "Board not found.\n");
-		goto free_io;
-	}
-
-	v4l2_ctrl_handler_init(hdl, 4);
-	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
-			V4L2_CID_BRIGHTNESS, 0, 255, 1, 139);
-	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
-			V4L2_CID_CONTRAST, 0, 255, 1, 70);
-	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
-			V4L2_CID_SATURATION, 0, 255, 1, 64);
-	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
-			V4L2_CID_HUE, 0, 255, 1, 0);
-	if (hdl->error) {
-		res = hdl->error;
-		goto free_hdl;
-	}
-
-	mutex_init(&dev->lock);
-	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
-	dev->vdev.v4l2_dev = v4l2_dev;
-	dev->vdev.ctrl_handler = hdl;
-	dev->vdev.fops = &pms_fops;
-	dev->vdev.ioctl_ops = &pms_ioctl_ops;
-	dev->vdev.release = video_device_release_empty;
-	dev->vdev.lock = &dev->lock;
-	dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
-	video_set_drvdata(&dev->vdev, dev);
-	dev->std = V4L2_STD_NTSC_M;
-	dev->height = 240;
-	dev->width = 320;
-	dev->depth = 16;
-	pms_swsense(dev, 75);
-	pms_resolution(dev, 320, 240);
-	pms_videosource(dev, 0);
-	pms_vcrinput(dev, 0);
-	v4l2_ctrl_handler_setup(hdl);
-	res = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr);
-	if (res >= 0)
-		return 0;
-
-free_hdl:
-	v4l2_ctrl_handler_free(hdl);
-	v4l2_device_unregister(&dev->v4l2_dev);
-free_io:
-	release_region(dev->io, 3);
-	release_region(0x9a01, 1);
-	iounmap(dev->mem);
-free_dev:
-	kfree(dev);
-	return res;
-}
-
-static int pms_remove(struct device *pdev, unsigned int card)
-{
-	struct pms *dev = dev_get_drvdata(pdev);
-
-	video_unregister_device(&dev->vdev);
-	v4l2_ctrl_handler_free(&dev->hdl);
-	release_region(dev->io, 3);
-	release_region(0x9a01, 1);
-	iounmap(dev->mem);
-	return 0;
-}
-
-static struct isa_driver pms_driver = {
-	.probe		= pms_probe,
-	.remove		= pms_remove,
-	.driver		= {
-		.name	= "pms",
-	},
-};
-
-static int __init pms_init(void)
-{
-	return isa_register_driver(&pms_driver, 1);
-}
-
-static void __exit pms_exit(void)
-{
-	isa_unregister_driver(&pms_driver);
-}
-
-module_init(pms_init);
-module_exit(pms_exit);
diff --git a/drivers/staging/media/parport/w9966.c b/drivers/staging/media/parport/w9966.c
deleted file mode 100644
index f7502f3a6a3c..000000000000
--- a/drivers/staging/media/parport/w9966.c
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
-	Winbond w9966cf Webcam parport driver.
-
-	Version 0.33
-
-	Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/*
-	Supported devices:
-	*Lifeview FlyCam Supra (using the Philips saa7111a chip)
-
-	Does any other model using the w9966 interface chip exist ?
-
-	Todo:
-
-	*Add a working EPP mode, since DMA ECP read isn't implemented
-	in the parport drivers. (That's why it's so sloow)
-
-	*Add support for other ccd-control chips than the saa7111
-	please send me feedback on what kind of chips you have.
-
-	*Add proper probing. I don't know what's wrong with the IEEE1284
-	parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
-	and nibble read seems to be broken for some peripherals.
-
-	*Add probing for onboard SRAM, port directions etc. (if possible)
-
-	*Add support for the hardware compressed modes (maybe using v4l2)
-
-	*Fix better support for the capture window (no skewed images, v4l
-	interface to capt. window)
-
-	*Probably some bugs that I don't know of
-
-	Please support me by sending feedback!
-
-	Changes:
-
-	Alan Cox:	Removed RGB mode for kernel merge, added THIS_MODULE
-			and owner support for newer module locks
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <linux/parport.h>
-
-/*#define DEBUG*/				/* Undef me for production */
-
-#ifdef DEBUG
-#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
-#else
-#define DPRINTF(x...)
-#endif
-
-/*
- *	Defines, simple typedefs etc.
- */
-
-#define W9966_DRIVERNAME	"W9966CF Webcam"
-#define W9966_MAXCAMS		4	/* Maximum number of cameras */
-#define W9966_RBUFFER		2048	/* Read buffer (must be an even number) */
-#define W9966_SRAMSIZE		131072	/* 128kb */
-#define W9966_SRAMID		0x02	/* check w9966cf.pdf */
-
-/* Empirically determined window limits */
-#define W9966_WND_MIN_X		16
-#define W9966_WND_MIN_Y		14
-#define W9966_WND_MAX_X		705
-#define W9966_WND_MAX_Y		253
-#define W9966_WND_MAX_W		(W9966_WND_MAX_X - W9966_WND_MIN_X)
-#define W9966_WND_MAX_H		(W9966_WND_MAX_Y - W9966_WND_MIN_Y)
-
-/* Keep track of our current state */
-#define W9966_STATE_PDEV	0x01
-#define W9966_STATE_CLAIMED	0x02
-#define W9966_STATE_VDEV	0x04
-
-#define W9966_I2C_W_ID		0x48
-#define W9966_I2C_R_ID		0x49
-#define W9966_I2C_R_DATA	0x08
-#define W9966_I2C_R_CLOCK	0x04
-#define W9966_I2C_W_DATA	0x02
-#define W9966_I2C_W_CLOCK	0x01
-
-struct w9966 {
-	struct v4l2_device v4l2_dev;
-	struct v4l2_ctrl_handler hdl;
-	unsigned char dev_state;
-	unsigned char i2c_state;
-	unsigned short ppmode;
-	struct parport *pport;
-	struct pardevice *pdev;
-	struct video_device vdev;
-	unsigned short width;
-	unsigned short height;
-	unsigned char brightness;
-	signed char contrast;
-	signed char color;
-	signed char hue;
-	struct mutex lock;
-};
-
-/*
- *	Module specific properties
- */
-
-MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
-MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.33.1");
-
-#ifdef MODULE
-static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
-#else
-static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
-#endif
-module_param_array(pardev, charp, NULL, 0);
-MODULE_PARM_DESC(pardev, "pardev: where to search for\n"
-		"\teach camera. 'aggressive' means brute-force search.\n"
-		"\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
-		"\tcam 1 to parport3 and search every parport for cam 2 etc...");
-
-static int parmode;
-module_param(parmode, int, 0);
-MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
-
-static int video_nr = -1;
-module_param(video_nr, int, 0);
-
-static struct w9966 w9966_cams[W9966_MAXCAMS];
-
-/*
- *	Private function defines
- */
-
-
-/* Set camera phase flags, so we know what to uninit when terminating */
-static inline void w9966_set_state(struct w9966 *cam, int mask, int val)
-{
-	cam->dev_state = (cam->dev_state & ~mask) ^ val;
-}
-
-/* Get camera phase flags */
-static inline int w9966_get_state(struct w9966 *cam, int mask, int val)
-{
-	return ((cam->dev_state & mask) == val);
-}
-
-/* Claim parport for ourself */
-static void w9966_pdev_claim(struct w9966 *cam)
-{
-	if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
-		return;
-	parport_claim_or_block(cam->pdev);
-	w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
-}
-
-/* Release parport for others to use */
-static void w9966_pdev_release(struct w9966 *cam)
-{
-	if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
-		return;
-	parport_release(cam->pdev);
-	w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
-}
-
-/* Read register from W9966 interface-chip
-   Expects a claimed pdev
-   -1 on error, else register data (byte) */
-static int w9966_read_reg(struct w9966 *cam, int reg)
-{
-	/* ECP, read, regtransfer, REG, REG, REG, REG, REG */
-	const unsigned char addr = 0x80 | (reg & 0x1f);
-	unsigned char val;
-
-	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
-		return -1;
-	if (parport_write(cam->pport, &addr, 1) != 1)
-		return -1;
-	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
-		return -1;
-	if (parport_read(cam->pport, &val, 1) != 1)
-		return -1;
-
-	return val;
-}
-
-/* Write register to W9966 interface-chip
-   Expects a claimed pdev
-   -1 on error */
-static int w9966_write_reg(struct w9966 *cam, int reg, int data)
-{
-	/* ECP, write, regtransfer, REG, REG, REG, REG, REG */
-	const unsigned char addr = 0xc0 | (reg & 0x1f);
-	const unsigned char val = data;
-
-	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
-		return -1;
-	if (parport_write(cam->pport, &addr, 1) != 1)
-		return -1;
-	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
-		return -1;
-	if (parport_write(cam->pport, &val, 1) != 1)
-		return -1;
-
-	return 0;
-}
-
-/*
- *	Ugly and primitive i2c protocol functions
- */
-
-/* Sets the data line on the i2c bus.
-   Expects a claimed pdev. */
-static void w9966_i2c_setsda(struct w9966 *cam, int state)
-{
-	if (state)
-		cam->i2c_state |= W9966_I2C_W_DATA;
-	else
-		cam->i2c_state &= ~W9966_I2C_W_DATA;
-
-	w9966_write_reg(cam, 0x18, cam->i2c_state);
-	udelay(5);
-}
-
-/* Get peripheral clock line
-   Expects a claimed pdev. */
-static int w9966_i2c_getscl(struct w9966 *cam)
-{
-	const unsigned char state = w9966_read_reg(cam, 0x18);
-	return ((state & W9966_I2C_R_CLOCK) > 0);
-}
-
-/* Sets the clock line on the i2c bus.
-   Expects a claimed pdev. -1 on error */
-static int w9966_i2c_setscl(struct w9966 *cam, int state)
-{
-	unsigned long timeout;
-
-	if (state)
-		cam->i2c_state |= W9966_I2C_W_CLOCK;
-	else
-		cam->i2c_state &= ~W9966_I2C_W_CLOCK;
-
-	w9966_write_reg(cam, 0x18, cam->i2c_state);
-	udelay(5);
-
-	/* we go to high, we also expect the peripheral to ack. */
-	if (state) {
-		timeout = jiffies + 100;
-		while (!w9966_i2c_getscl(cam)) {
-			if (time_after(jiffies, timeout))
-				return -1;
-		}
-	}
-	return 0;
-}
-
-#if 0
-/* Get peripheral data line
-   Expects a claimed pdev. */
-static int w9966_i2c_getsda(struct w9966 *cam)
-{
-	const unsigned char state = w9966_read_reg(cam, 0x18);
-	return ((state & W9966_I2C_R_DATA) > 0);
-}
-#endif
-
-/* Write a byte with ack to the i2c bus.
-   Expects a claimed pdev. -1 on error */
-static int w9966_i2c_wbyte(struct w9966 *cam, int data)
-{
-	int i;
-
-	for (i = 7; i >= 0; i--) {
-		w9966_i2c_setsda(cam, (data >> i) & 0x01);
-
-		if (w9966_i2c_setscl(cam, 1) == -1)
-			return -1;
-		w9966_i2c_setscl(cam, 0);
-	}
-
-	w9966_i2c_setsda(cam, 1);
-
-	if (w9966_i2c_setscl(cam, 1) == -1)
-		return -1;
-	w9966_i2c_setscl(cam, 0);
-
-	return 0;
-}
-
-/* Read a data byte with ack from the i2c-bus
-   Expects a claimed pdev. -1 on error */
-#if 0
-static int w9966_i2c_rbyte(struct w9966 *cam)
-{
-	unsigned char data = 0x00;
-	int i;
-
-	w9966_i2c_setsda(cam, 1);
-
-	for (i = 0; i < 8; i++) {
-		if (w9966_i2c_setscl(cam, 1) == -1)
-			return -1;
-		data = data << 1;
-		if (w9966_i2c_getsda(cam))
-			data |= 0x01;
-
-		w9966_i2c_setscl(cam, 0);
-	}
-	return data;
-}
-#endif
-
-/* Read a register from the i2c device.
-   Expects claimed pdev. -1 on error */
-#if 0
-static int w9966_read_reg_i2c(struct w9966 *cam, int reg)
-{
-	int data;
-
-	w9966_i2c_setsda(cam, 0);
-	w9966_i2c_setscl(cam, 0);
-
-	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
-	    w9966_i2c_wbyte(cam, reg) == -1)
-		return -1;
-
-	w9966_i2c_setsda(cam, 1);
-	if (w9966_i2c_setscl(cam, 1) == -1)
-		return -1;
-	w9966_i2c_setsda(cam, 0);
-	w9966_i2c_setscl(cam, 0);
-
-	if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
-		return -1;
-	data = w9966_i2c_rbyte(cam);
-	if (data == -1)
-		return -1;
-
-	w9966_i2c_setsda(cam, 0);
-
-	if (w9966_i2c_setscl(cam, 1) == -1)
-		return -1;
-	w9966_i2c_setsda(cam, 1);
-
-	return data;
-}
-#endif
-
-/* Write a register to the i2c device.
-   Expects claimed pdev. -1 on error */
-static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data)
-{
-	w9966_i2c_setsda(cam, 0);
-	w9966_i2c_setscl(cam, 0);
-
-	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
-			w9966_i2c_wbyte(cam, reg) == -1 ||
-			w9966_i2c_wbyte(cam, data) == -1)
-		return -1;
-
-	w9966_i2c_setsda(cam, 0);
-	if (w9966_i2c_setscl(cam, 1) == -1)
-		return -1;
-
-	w9966_i2c_setsda(cam, 1);
-
-	return 0;
-}
-
-/* Find a good length for capture window (used both for W and H)
-   A bit ugly but pretty functional. The capture length
-   have to match the downscale */
-static int w9966_findlen(int near, int size, int maxlen)
-{
-	int bestlen = size;
-	int besterr = abs(near - bestlen);
-	int len;
-
-	for (len = size + 1; len < maxlen; len++) {
-		int err;
-		if (((64 * size) % len) != 0)
-			continue;
-
-		err = abs(near - len);
-
-		/* Only continue as long as we keep getting better values */
-		if (err > besterr)
-			break;
-
-		besterr = err;
-		bestlen = len;
-	}
-
-	return bestlen;
-}
-
-/* Modify capture window (if necessary)
-   and calculate downscaling
-   Return -1 on error */
-static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
-{
-	int maxlen = max - min;
-	int len = *end - *beg + 1;
-	int newlen = w9966_findlen(len, size, maxlen);
-	int err = newlen - len;
-
-	/* Check for bad format */
-	if (newlen > maxlen || newlen < size)
-		return -1;
-
-	/* Set factor (6 bit fixed) */
-	*factor = (64 * size) / newlen;
-	if (*factor == 64)
-		*factor = 0x00;	/* downscale is disabled */
-	else
-		*factor |= 0x80; /* set downscale-enable bit */
-
-	/* Modify old beginning and end */
-	*beg -= err / 2;
-	*end += err - (err / 2);
-
-	/* Move window if outside borders */
-	if (*beg < min) {
-		*end += min - *beg;
-		*beg += min - *beg;
-	}
-	if (*end > max) {
-		*beg -= *end - max;
-		*end -= *end - max;
-	}
-
-	return 0;
-}
-
-/* Setup the cameras capture window etc.
-   Expects a claimed pdev
-   return -1 on error */
-static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h)
-{
-	unsigned int i;
-	unsigned int enh_s, enh_e;
-	unsigned char scale_x, scale_y;
-	unsigned char regs[0x1c];
-	unsigned char saa7111_regs[] = {
-		0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
-		0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
-		0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
-	};
-
-
-	if (w * h * 2 > W9966_SRAMSIZE) {
-		DPRINTF("capture window exceeds SRAM size!.\n");
-		w = 200; h = 160;	/* Pick default values */
-	}
-
-	w &= ~0x1;
-	if (w < 2)
-		w = 2;
-	if (h < 1)
-		h = 1;
-	if (w > W9966_WND_MAX_W)
-		w = W9966_WND_MAX_W;
-	if (h > W9966_WND_MAX_H)
-		h = W9966_WND_MAX_H;
-
-	cam->width = w;
-	cam->height = h;
-
-	enh_s = 0;
-	enh_e = w * h * 2;
-
-	/* Modify capture window if necessary and calculate downscaling */
-	if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
-			w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0)
-		return -1;
-
-	DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
-			w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80);
-
-	/* Setup registers */
-	regs[0x00] = 0x00;			/* Set normal operation */
-	regs[0x01] = 0x18;			/* Capture mode */
-	regs[0x02] = scale_y;			/* V-scaling */
-	regs[0x03] = scale_x;			/* H-scaling */
-
-	/* Capture window */
-	regs[0x04] = (x1 & 0x0ff);		/* X-start (8 low bits) */
-	regs[0x05] = (x1 & 0x300)>>8;		/* X-start (2 high bits) */
-	regs[0x06] = (y1 & 0x0ff);		/* Y-start (8 low bits) */
-	regs[0x07] = (y1 & 0x300)>>8;		/* Y-start (2 high bits) */
-	regs[0x08] = (x2 & 0x0ff);		/* X-end (8 low bits) */
-	regs[0x09] = (x2 & 0x300)>>8;		/* X-end (2 high bits) */
-	regs[0x0a] = (y2 & 0x0ff);		/* Y-end (8 low bits) */
-
-	regs[0x0c] = W9966_SRAMID;		/* SRAM-banks (1x 128kb) */
-
-	/* Enhancement layer */
-	regs[0x0d] = (enh_s & 0x000ff);		/* Enh. start (0-7) */
-	regs[0x0e] = (enh_s & 0x0ff00) >> 8;	/* Enh. start (8-15) */
-	regs[0x0f] = (enh_s & 0x70000) >> 16;	/* Enh. start (16-17/18??) */
-	regs[0x10] = (enh_e & 0x000ff);		/* Enh. end (0-7) */
-	regs[0x11] = (enh_e & 0x0ff00) >> 8;	/* Enh. end (8-15) */
-	regs[0x12] = (enh_e & 0x70000) >> 16;	/* Enh. end (16-17/18??) */
-
-	/* Misc */
-	regs[0x13] = 0x40;			/* VEE control (raw 4:2:2) */
-	regs[0x17] = 0x00;			/* ??? */
-	regs[0x18] = cam->i2c_state = 0x00;	/* Serial bus */
-	regs[0x19] = 0xff;			/* I/O port direction control */
-	regs[0x1a] = 0xff;			/* I/O port data register */
-	regs[0x1b] = 0x10;			/* ??? */
-
-	/* SAA7111 chip settings */
-	saa7111_regs[0x0a] = cam->brightness;
-	saa7111_regs[0x0b] = cam->contrast;
-	saa7111_regs[0x0c] = cam->color;
-	saa7111_regs[0x0d] = cam->hue;
-
-	/* Reset (ECP-fifo & serial-bus) */
-	if (w9966_write_reg(cam, 0x00, 0x03) == -1)
-		return -1;
-
-	/* Write regs to w9966cf chip */
-	for (i = 0; i < 0x1c; i++)
-		if (w9966_write_reg(cam, i, regs[i]) == -1)
-			return -1;
-
-	/* Write regs to saa7111 chip */
-	for (i = 0; i < 0x20; i++)
-		if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1)
-			return -1;
-
-	return 0;
-}
-
-/*
- *	Video4linux interfacing
- */
-
-static int cam_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *vcap)
-{
-	struct w9966 *cam = video_drvdata(file);
-
-	strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver));
-	strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card));
-	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
-	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
-	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
-{
-	if (vin->index > 0)
-		return -EINVAL;
-	strlcpy(vin->name, "Camera", sizeof(vin->name));
-	vin->type = V4L2_INPUT_TYPE_CAMERA;
-	vin->audioset = 0;
-	vin->tuner = 0;
-	vin->std = 0;
-	vin->status = 0;
-	return 0;
-}
-
-static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
-{
-	*inp = 0;
-	return 0;
-}
-
-static int cam_s_input(struct file *file, void *fh, unsigned int inp)
-{
-	return (inp > 0) ? -EINVAL : 0;
-}
-
-static int cam_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct w9966 *cam =
-		container_of(ctrl->handler, struct w9966, hdl);
-	int ret = 0;
-
-	mutex_lock(&cam->lock);
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		cam->brightness = ctrl->val;
-		break;
-	case V4L2_CID_CONTRAST:
-		cam->contrast = ctrl->val;
-		break;
-	case V4L2_CID_SATURATION:
-		cam->color = ctrl->val;
-		break;
-	case V4L2_CID_HUE:
-		cam->hue = ctrl->val;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	if (ret == 0) {
-		w9966_pdev_claim(cam);
-
-		if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 ||
-		    w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 ||
-		    w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 ||
-		    w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) {
-			ret = -EIO;
-		}
-
-		w9966_pdev_release(cam);
-	}
-	mutex_unlock(&cam->lock);
-	return ret;
-}
-
-static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct w9966 *cam = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	pix->width = cam->width;
-	pix->height = cam->height;
-	pix->pixelformat = V4L2_PIX_FMT_YUYV;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = 2 * cam->width;
-	pix->sizeimage = 2 * cam->width * cam->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	return 0;
-}
-
-static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
-	if (pix->width < 2)
-		pix->width = 2;
-	if (pix->height < 1)
-		pix->height = 1;
-	if (pix->width > W9966_WND_MAX_W)
-		pix->width = W9966_WND_MAX_W;
-	if (pix->height > W9966_WND_MAX_H)
-		pix->height = W9966_WND_MAX_H;
-	pix->pixelformat = V4L2_PIX_FMT_YUYV;
-	pix->field = V4L2_FIELD_NONE;
-	pix->bytesperline = 2 * pix->width;
-	pix->sizeimage = 2 * pix->width * pix->height;
-	/* Just a guess */
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	return 0;
-}
-
-static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-	struct w9966 *cam = video_drvdata(file);
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-	int ret = cam_try_fmt_vid_cap(file, fh, fmt);
-
-	if (ret)
-		return ret;
-
-	mutex_lock(&cam->lock);
-	/* Update camera regs */
-	w9966_pdev_claim(cam);
-	ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height);
-	w9966_pdev_release(cam);
-	mutex_unlock(&cam->lock);
-	return ret;
-}
-
-static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
-{
-	static struct v4l2_fmtdesc formats[] = {
-		{ 0, 0, 0,
-		  "YUV 4:2:2", V4L2_PIX_FMT_YUYV,
-		  { 0, 0, 0, 0 }
-		},
-	};
-	enum v4l2_buf_type type = fmt->type;
-
-	if (fmt->index > 0)
-		return -EINVAL;
-
-	*fmt = formats[fmt->index];
-	fmt->type = type;
-	return 0;
-}
-
-/* Capture data */
-static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
-		size_t count, loff_t *ppos)
-{
-	struct w9966 *cam = video_drvdata(file);
-	unsigned char addr = 0xa0;	/* ECP, read, CCD-transfer, 00000 */
-	unsigned char __user *dest = (unsigned char __user *)buf;
-	unsigned long dleft = count;
-	unsigned char *tbuf;
-
-	/* Why would anyone want more than this?? */
-	if (count > cam->width * cam->height * 2)
-		return -EINVAL;
-
-	mutex_lock(&cam->lock);
-	w9966_pdev_claim(cam);
-	w9966_write_reg(cam, 0x00, 0x02);	/* Reset ECP-FIFO buffer */
-	w9966_write_reg(cam, 0x00, 0x00);	/* Return to normal operation */
-	w9966_write_reg(cam, 0x01, 0x98);	/* Enable capture */
-
-	/* write special capture-addr and negotiate into data transfer */
-	if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) ||
-			(parport_write(cam->pport, &addr, 1) != 1) ||
-			(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) {
-		w9966_pdev_release(cam);
-		mutex_unlock(&cam->lock);
-		return -EFAULT;
-	}
-
-	tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
-	if (tbuf == NULL) {
-		count = -ENOMEM;
-		goto out;
-	}
-
-	while (dleft > 0) {
-		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
-
-		if (parport_read(cam->pport, tbuf, tsize) < tsize) {
-			count = -EFAULT;
-			goto out;
-		}
-		if (copy_to_user(dest, tbuf, tsize) != 0) {
-			count = -EFAULT;
-			goto out;
-		}
-		dest += tsize;
-		dleft -= tsize;
-	}
-
-	w9966_write_reg(cam, 0x01, 0x18);	/* Disable capture */
-
-out:
-	kfree(tbuf);
-	w9966_pdev_release(cam);
-	mutex_unlock(&cam->lock);
-
-	return count;
-}
-
-static const struct v4l2_file_operations w9966_fops = {
-	.owner		= THIS_MODULE,
-	.open		= v4l2_fh_open,
-	.release	= v4l2_fh_release,
-	.poll		= v4l2_ctrl_poll,
-	.unlocked_ioctl = video_ioctl2,
-	.read           = w9966_v4l_read,
-};
-
-static const struct v4l2_ioctl_ops w9966_ioctl_ops = {
-	.vidioc_querycap    		    = cam_querycap,
-	.vidioc_g_input      		    = cam_g_input,
-	.vidioc_s_input      		    = cam_s_input,
-	.vidioc_enum_input   		    = cam_enum_input,
-	.vidioc_enum_fmt_vid_cap 	    = cam_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap 		    = cam_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap  		    = cam_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap  	    = cam_try_fmt_vid_cap,
-	.vidioc_log_status		    = v4l2_ctrl_log_status,
-	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
-};
-
-static const struct v4l2_ctrl_ops cam_ctrl_ops = {
-	.s_ctrl = cam_s_ctrl,
-};
-
-
-/* Initialize camera device. Setup all internal flags, set a
-   default video mode, setup ccd-chip, register v4l device etc..
-   Also used for 'probing' of hardware.
-   -1 on error */
-static int w9966_init(struct w9966 *cam, struct parport *port)
-{
-	struct v4l2_device *v4l2_dev = &cam->v4l2_dev;
-
-	if (cam->dev_state != 0)
-		return -1;
-
-	strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));
-
-	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
-		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
-		return -1;
-	}
-
-	v4l2_ctrl_handler_init(&cam->hdl, 4);
-	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
-			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
-			  V4L2_CID_CONTRAST, -64, 64, 1, 64);
-	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
-			  V4L2_CID_SATURATION, -64, 64, 1, 64);
-	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
-			  V4L2_CID_HUE, -128, 127, 1, 0);
-	if (cam->hdl.error) {
-		v4l2_err(v4l2_dev, "couldn't register controls\n");
-		return -1;
-	}
-	cam->pport = port;
-	cam->brightness = 128;
-	cam->contrast = 64;
-	cam->color = 64;
-	cam->hue = 0;
-
-	/* Select requested transfer mode */
-	switch (parmode) {
-	default:	/* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
-	case 0:
-		if (port->modes & PARPORT_MODE_ECP)
-			cam->ppmode = IEEE1284_MODE_ECP;
-		else if (port->modes & PARPORT_MODE_EPP)
-			cam->ppmode = IEEE1284_MODE_EPP;
-		else
-			cam->ppmode = IEEE1284_MODE_ECP;
-		break;
-	case 1:		/* hw- or sw-ecp */
-		cam->ppmode = IEEE1284_MODE_ECP;
-		break;
-	case 2:		/* hw- or sw-epp */
-		cam->ppmode = IEEE1284_MODE_EPP;
-		break;
-	}
-
-	/* Tell the parport driver that we exists */
-	cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
-	if (cam->pdev == NULL) {
-		DPRINTF("parport_register_device() failed\n");
-		return -1;
-	}
-	w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
-
-	w9966_pdev_claim(cam);
-
-	/* Setup a default capture mode */
-	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
-		DPRINTF("w9966_setup() failed.\n");
-		return -1;
-	}
-
-	w9966_pdev_release(cam);
-
-	/* Fill in the video_device struct and register us to v4l */
-	strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name));
-	cam->vdev.v4l2_dev = v4l2_dev;
-	cam->vdev.fops = &w9966_fops;
-	cam->vdev.ioctl_ops = &w9966_ioctl_ops;
-	cam->vdev.release = video_device_release_empty;
-	cam->vdev.ctrl_handler = &cam->hdl;
-	video_set_drvdata(&cam->vdev, cam);
-
-	mutex_init(&cam->lock);
-
-	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
-		return -1;
-
-	w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
-
-	/* All ok */
-	v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
-			cam->pport->name);
-	return 0;
-}
-
-
-/* Terminate everything gracefully */
-static void w9966_term(struct w9966 *cam)
-{
-	/* Unregister from v4l */
-	if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
-		video_unregister_device(&cam->vdev);
-		w9966_set_state(cam, W9966_STATE_VDEV, 0);
-	}
-
-	v4l2_ctrl_handler_free(&cam->hdl);
-
-	/* Terminate from IEEE1284 mode and release pdev block */
-	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
-		w9966_pdev_claim(cam);
-		parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
-		w9966_pdev_release(cam);
-	}
-
-	/* Unregister from parport */
-	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
-		parport_unregister_device(cam->pdev);
-		w9966_set_state(cam, W9966_STATE_PDEV, 0);
-	}
-	memset(cam, 0, sizeof(*cam));
-}
-
-
-/* Called once for every parport on init */
-static void w9966_attach(struct parport *port)
-{
-	int i;
-
-	for (i = 0; i < W9966_MAXCAMS; i++) {
-		if (w9966_cams[i].dev_state != 0)	/* Cam is already assigned */
-			continue;
-		if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) {
-			if (w9966_init(&w9966_cams[i], port) != 0)
-				w9966_term(&w9966_cams[i]);
-			break;	/* return */
-		}
-	}
-}
-
-/* Called once for every parport on termination */
-static void w9966_detach(struct parport *port)
-{
-	int i;
-
-	for (i = 0; i < W9966_MAXCAMS; i++)
-		if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
-			w9966_term(&w9966_cams[i]);
-}
-
-
-static struct parport_driver w9966_ppd = {
-	.name = W9966_DRIVERNAME,
-	.attach = w9966_attach,
-	.detach = w9966_detach,
-};
-
-/* Module entry point */
-static int __init w9966_mod_init(void)
-{
-	int i;
-
-	for (i = 0; i < W9966_MAXCAMS; i++)
-		w9966_cams[i].dev_state = 0;
-
-	return parport_register_driver(&w9966_ppd);
-}
-
-/* Module cleanup */
-static void __exit w9966_mod_term(void)
-{
-	parport_unregister_driver(&w9966_ppd);
-}
-
-module_init(w9966_mod_init);
-module_exit(w9966_mod_term);
diff --git a/drivers/staging/media/tlg2300/Kconfig b/drivers/staging/media/tlg2300/Kconfig
deleted file mode 100644
index 77d8753f6ba4..000000000000
--- a/drivers/staging/media/tlg2300/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-config VIDEO_TLG2300
-	tristate "Telegent TLG2300 USB video capture support (Deprecated)"
-	depends on VIDEO_DEV && I2C && SND && DVB_CORE
-	depends on MEDIA_USB_SUPPORT
-	select VIDEO_TUNER
-	select VIDEO_TVEEPROM
-	depends on RC_CORE
-	select VIDEOBUF_VMALLOC
-	select SND_PCM
-	select VIDEOBUF_DVB
-
-	---help---
-	  This is a video4linux driver for Telegent tlg2300 based TV cards.
-	  The driver supports V4L2, DVB-T and radio.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called poseidon
diff --git a/drivers/staging/media/tlg2300/Makefile b/drivers/staging/media/tlg2300/Makefile
deleted file mode 100644
index 137f8e38cdec..000000000000
--- a/drivers/staging/media/tlg2300/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
-
-obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
-
-ccflags-y += -Idrivers/media/i2c
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-
diff --git a/drivers/staging/media/tlg2300/pd-alsa.c b/drivers/staging/media/tlg2300/pd-alsa.c
deleted file mode 100644
index dd8fe100590f..000000000000
--- a/drivers/staging/media/tlg2300/pd-alsa.c
+++ /dev/null
@@ -1,337 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/init.h>
-#include <linux/sound.h>
-#include <linux/spinlock.h>
-#include <linux/soundcard.h>
-#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
-#include <linux/module.h>
-#include <linux/gfp.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/info.h>
-#include <sound/initval.h>
-#include <sound/control.h>
-#include <media/v4l2-common.h>
-#include "pd-common.h"
-#include "vendorcmds.h"
-
-static void complete_handler_audio(struct urb *urb);
-#define AUDIO_EP	(0x83)
-#define AUDIO_BUF_SIZE	(512)
-#define PERIOD_SIZE	(1024 * 8)
-#define PERIOD_MIN	(4)
-#define PERIOD_MAX 	PERIOD_MIN
-
-static struct snd_pcm_hardware snd_pd_hw_capture = {
-	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
-		SNDRV_PCM_INFO_MMAP           |
-		SNDRV_PCM_INFO_INTERLEAVED |
-		SNDRV_PCM_INFO_MMAP_VALID,
-
-	.formats = SNDRV_PCM_FMTBIT_S16_LE,
-	.rates = SNDRV_PCM_RATE_48000,
-
-	.rate_min = 48000,
-	.rate_max = 48000,
-	.channels_min = 2,
-	.channels_max = 2,
-	.buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN,
-	.period_bytes_min = PERIOD_SIZE,
-	.period_bytes_max = PERIOD_SIZE,
-	.periods_min = PERIOD_MIN,
-	.periods_max = PERIOD_MAX,
-	/*
-	.buffer_bytes_max = 62720 * 8,
-	.period_bytes_min = 64,
-	.period_bytes_max = 12544,
-	.periods_min = 2,
-	.periods_max = 98
-	*/
-};
-
-static int snd_pd_capture_open(struct snd_pcm_substream *substream)
-{
-	struct poseidon *p = snd_pcm_substream_chip(substream);
-	struct poseidon_audio *pa = &p->audio;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-
-	if (!p)
-		return -ENODEV;
-	pa->users++;
-	pa->card_close 		= 0;
-	pa->capture_pcm_substream	= substream;
-	runtime->private_data		= p;
-
-	runtime->hw = snd_pd_hw_capture;
-	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-	usb_autopm_get_interface(p->interface);
-	kref_get(&p->kref);
-	return 0;
-}
-
-static int snd_pd_pcm_close(struct snd_pcm_substream *substream)
-{
-	struct poseidon *p = snd_pcm_substream_chip(substream);
-	struct poseidon_audio *pa = &p->audio;
-
-	pa->users--;
-	pa->card_close 		= 1;
-	usb_autopm_put_interface(p->interface);
-	kref_put(&p->kref, poseidon_delete);
-	return 0;
-}
-
-static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream,
-					struct snd_pcm_hw_params *hw_params)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	unsigned int size;
-
-	size = params_buffer_bytes(hw_params);
-	if (runtime->dma_area) {
-		if (runtime->dma_bytes > size)
-			return 0;
-		vfree(runtime->dma_area);
-	}
-	runtime->dma_area = vmalloc(size);
-	if (!runtime->dma_area)
-		return -ENOMEM;
-	else
-		runtime->dma_bytes = size;
-	return 0;
-}
-
-static int audio_buf_free(struct poseidon *p)
-{
-	struct poseidon_audio *pa = &p->audio;
-	int i;
-
-	for (i = 0; i < AUDIO_BUFS; i++)
-		if (pa->urb_array[i])
-			usb_kill_urb(pa->urb_array[i]);
-	free_all_urb_generic(pa->urb_array, AUDIO_BUFS);
-	logpm();
-	return 0;
-}
-
-static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream)
-{
-	struct poseidon *p = snd_pcm_substream_chip(substream);
-
-	logpm();
-	audio_buf_free(p);
-	return 0;
-}
-
-static int snd_pd_prepare(struct snd_pcm_substream *substream)
-{
-	return 0;
-}
-
-#define AUDIO_TRAILER_SIZE	(16)
-static inline void handle_audio_data(struct urb *urb, int *period_elapsed)
-{
-	struct poseidon_audio *pa = urb->context;
-	struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime;
-
-	int stride	= runtime->frame_bits >> 3;
-	int len		= urb->actual_length / stride;
-	unsigned char *cp	= urb->transfer_buffer;
-	unsigned int oldptr	= pa->rcv_position;
-
-	if (urb->actual_length == AUDIO_BUF_SIZE - 4)
-		len -= (AUDIO_TRAILER_SIZE / stride);
-
-	/* do the copy */
-	if (oldptr + len >= runtime->buffer_size) {
-		unsigned int cnt = runtime->buffer_size - oldptr;
-
-		memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride);
-		memcpy(runtime->dma_area, (cp + cnt * stride),
-					(len * stride - cnt * stride));
-	} else
-		memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
-
-	/* update the statas */
-	snd_pcm_stream_lock(pa->capture_pcm_substream);
-	pa->rcv_position	+= len;
-	if (pa->rcv_position >= runtime->buffer_size)
-		pa->rcv_position -= runtime->buffer_size;
-
-	pa->copied_position += (len);
-	if (pa->copied_position >= runtime->period_size) {
-		pa->copied_position -= runtime->period_size;
-		*period_elapsed = 1;
-	}
-	snd_pcm_stream_unlock(pa->capture_pcm_substream);
-}
-
-static void complete_handler_audio(struct urb *urb)
-{
-	struct poseidon_audio *pa = urb->context;
-	struct snd_pcm_substream *substream = pa->capture_pcm_substream;
-	int    period_elapsed = 0;
-	int    ret;
-
-	if (1 == pa->card_close || pa->capture_stream != STREAM_ON)
-		return;
-
-	if (urb->status != 0) {
-		/*if (urb->status == -ESHUTDOWN)*/
-			return;
-	}
-
-	if (substream) {
-		if (urb->actual_length) {
-			handle_audio_data(urb, &period_elapsed);
-			if (period_elapsed)
-				snd_pcm_period_elapsed(substream);
-		}
-	}
-
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret < 0)
-		log("audio urb failed (errcod = %i)", ret);
-	return;
-}
-
-static int fire_audio_urb(struct poseidon *p)
-{
-	int i, ret = 0;
-	struct poseidon_audio *pa = &p->audio;
-
-	alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS,
-			p->udev, AUDIO_EP,
-			AUDIO_BUF_SIZE, GFP_ATOMIC,
-			complete_handler_audio, pa);
-
-	for (i = 0; i < AUDIO_BUFS; i++) {
-		ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL);
-		if (ret)
-			log("urb err : %d", ret);
-	}
-	log();
-	return ret;
-}
-
-static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct poseidon *p = snd_pcm_substream_chip(substream);
-	struct poseidon_audio *pa = &p->audio;
-
-	if (debug_mode)
-		log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_START:
-		if (pa->capture_stream == STREAM_ON)
-			return 0;
-
-		pa->rcv_position = pa->copied_position = 0;
-		pa->capture_stream = STREAM_ON;
-
-		if (in_hibernation(p))
-			return 0;
-		fire_audio_urb(p);
-		return 0;
-
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-		pa->capture_stream = STREAM_SUSPEND;
-		return 0;
-	case SNDRV_PCM_TRIGGER_STOP:
-		pa->capture_stream = STREAM_OFF;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-static snd_pcm_uframes_t
-snd_pd_capture_pointer(struct snd_pcm_substream *substream)
-{
-	struct poseidon *p = snd_pcm_substream_chip(substream);
-	struct poseidon_audio *pa = &p->audio;
-	return pa->rcv_position;
-}
-
-static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs,
-					     unsigned long offset)
-{
-	void *pageptr = subs->runtime->dma_area + offset;
-	return vmalloc_to_page(pageptr);
-}
-
-static struct snd_pcm_ops pcm_capture_ops = {
-	.open      = snd_pd_capture_open,
-	.close     = snd_pd_pcm_close,
-	.ioctl     = snd_pcm_lib_ioctl,
-	.hw_params = snd_pd_hw_capture_params,
-	.hw_free   = snd_pd_hw_capture_free,
-	.prepare   = snd_pd_prepare,
-	.trigger   = snd_pd_capture_trigger,
-	.pointer   = snd_pd_capture_pointer,
-	.page      = snd_pcm_pd_get_page,
-};
-
-#ifdef CONFIG_PM
-int pm_alsa_suspend(struct poseidon *p)
-{
-	logpm(p);
-	audio_buf_free(p);
-	return 0;
-}
-
-int pm_alsa_resume(struct poseidon *p)
-{
-	logpm(p);
-	fire_audio_urb(p);
-	return 0;
-}
-#endif
-
-int poseidon_audio_init(struct poseidon *p)
-{
-	struct poseidon_audio *pa = &p->audio;
-	struct snd_card *card;
-	struct snd_pcm *pcm;
-	int ret;
-
-	ret = snd_card_new(&p->interface->dev, -1, "Telegent",
-			   THIS_MODULE, 0, &card);
-	if (ret != 0)
-		return ret;
-
-	ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
-	if (ret < 0) {
-		snd_card_free(card);
-		return ret;
-	}
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
-	pcm->info_flags   = 0;
-	pcm->private_data = p;
-	strcpy(pcm->name, "poseidon audio capture");
-
-	strcpy(card->driver, "ALSA driver");
-	strcpy(card->shortname, "poseidon Audio");
-	strcpy(card->longname, "poseidon ALSA Audio");
-
-	if (snd_card_register(card)) {
-		snd_card_free(card);
-		return -ENOMEM;
-	}
-	pa->card = card;
-	return 0;
-}
-
-int poseidon_audio_free(struct poseidon *p)
-{
-	struct poseidon_audio *pa = &p->audio;
-
-	if (pa->card)
-		snd_card_free(pa->card);
-	return 0;
-}
diff --git a/drivers/staging/media/tlg2300/pd-common.h b/drivers/staging/media/tlg2300/pd-common.h
deleted file mode 100644
index 9e23ad32d2fe..000000000000
--- a/drivers/staging/media/tlg2300/pd-common.h
+++ /dev/null
@@ -1,271 +0,0 @@
-#ifndef PD_COMMON_H
-#define PD_COMMON_H
-
-#include <linux/fs.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/videodev2.h>
-#include <linux/semaphore.h>
-#include <linux/usb.h>
-#include <linux/poll.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#include "dvb_frontend.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dmxdev.h"
-
-#define SBUF_NUM	8
-#define MAX_BUFFER_NUM	6
-#define PK_PER_URB	32
-#define ISO_PKT_SIZE	3072
-
-#define POSEIDON_STATE_NONE		(0x0000)
-#define POSEIDON_STATE_ANALOG		(0x0001)
-#define POSEIDON_STATE_FM		(0x0002)
-#define POSEIDON_STATE_DVBT		(0x0004)
-#define POSEIDON_STATE_DISCONNECT	(0x0080)
-
-#define PM_SUSPEND_DELAY	3
-
-#define V4L_PAL_VBI_LINES	18
-#define V4L_NTSC_VBI_LINES	12
-#define V4L_PAL_VBI_FRAMESIZE	(V4L_PAL_VBI_LINES * 1440 * 2)
-#define V4L_NTSC_VBI_FRAMESIZE	(V4L_NTSC_VBI_LINES * 1440 * 2)
-
-#define TUNER_FREQ_MIN		(45000000U)
-#define TUNER_FREQ_MAX		(862000000U)
-
-struct vbi_data {
-	struct video_device	v_dev;
-	struct video_data	*video;
-	struct front_face	*front;
-
-	unsigned int		copied;
-	unsigned int		vbi_size; /* the whole size of two fields */
-	int 			users;
-};
-
-/*
- * This is the running context of the video, it is useful for
- * resume()
- */
-struct running_context {
-	u32		freq;		/* VIDIOC_S_FREQUENCY */
-	int		audio_idx;	/* VIDIOC_S_TUNER    */
-	v4l2_std_id	tvnormid;	/* VIDIOC_S_STD     */
-	int		sig_index;	/* VIDIOC_S_INPUT  */
-	struct v4l2_pix_format pix;	/* VIDIOC_S_FMT   */
-};
-
-struct video_data {
-	/* v4l2 video device */
-	struct video_device	v_dev;
-	struct v4l2_ctrl_handler ctrl_handler;
-
-	/* the working context */
-	struct running_context	context;
-
-	/* for data copy */
-	int		field_count;
-
-	char		*dst;
-	int		lines_copied;
-	int		prev_left;
-
-	int		lines_per_field;
-	int		lines_size;
-
-	/* for communication */
-	u8			endpoint_addr;
-	struct urb 		*urb_array[SBUF_NUM];
-	struct vbi_data		*vbi;
-	struct poseidon 	*pd;
-	struct front_face	*front;
-
-	int			is_streaming;
-	int			users;
-
-	/* for bubble handler */
-	struct work_struct	bubble_work;
-};
-
-enum pcm_stream_state {
-	STREAM_OFF,
-	STREAM_ON,
-	STREAM_SUSPEND,
-};
-
-#define AUDIO_BUFS (3)
-#define CAPTURE_STREAM_EN 1
-struct poseidon_audio {
-	struct urb		*urb_array[AUDIO_BUFS];
-	unsigned int 		copied_position;
-	struct snd_pcm_substream   *capture_pcm_substream;
-
-	unsigned int 		rcv_position;
-	struct	snd_card	*card;
-	int 			card_close;
-
-	int 			users;
-	int			pm_state;
-	enum pcm_stream_state 	capture_stream;
-};
-
-struct radio_data {
-	__u32		fm_freq;
-	unsigned int	is_radio_streaming;
-	int		pre_emphasis;
-	struct video_device fm_dev;
-	struct v4l2_ctrl_handler ctrl_handler;
-};
-
-#define DVB_SBUF_NUM		4
-#define DVB_URB_BUF_SIZE	0x2000
-struct pd_dvb_adapter {
-	struct dvb_adapter	dvb_adap;
-	struct dvb_frontend	dvb_fe;
-	struct dmxdev		dmxdev;
-	struct dvb_demux	demux;
-
-	atomic_t		users;
-	atomic_t		active_feed;
-
-	/* data transfer */
-	s32			is_streaming;
-	struct urb		*urb_array[DVB_SBUF_NUM];
-	struct poseidon		*pd_device;
-	u8			ep_addr;
-	u8			reserved[3];
-
-	/* data for power resume*/
-	struct dtv_frontend_properties fe_param;
-
-	/* for channel scanning */
-	int		prev_freq;
-	int		bandwidth;
-	unsigned long	last_jiffies;
-};
-
-struct front_face {
-	/* use this field to distinguish VIDEO and VBI */
-	enum v4l2_buf_type	type;
-
-	/* for host */
-	struct videobuf_queue	q;
-
-	/* the bridge for host and device */
-	struct videobuf_buffer	*curr_frame;
-
-	/* for device */
-	spinlock_t		queue_lock;
-	struct list_head	active;
-	struct poseidon		*pd;
-};
-
-struct poseidon {
-	struct list_head	device_list;
-
-	struct mutex		lock;
-	struct kref		kref;
-
-	/* for V4L2 */
-	struct v4l2_device	v4l2_dev;
-
-	/* hardware info */
-	struct usb_device	*udev;
-	struct usb_interface	*interface;
-	int 			cur_transfer_mode;
-
-	struct video_data	video_data;	/* video */
-	struct vbi_data		vbi_data;	/* vbi	 */
-	struct poseidon_audio	audio;		/* audio (alsa) */
-	struct radio_data	radio_data;	/* FM	 */
-	struct pd_dvb_adapter	dvb_data;	/* DVB	 */
-
-	u32			state;
-	struct file		*file_for_stream; /* the active stream*/
-
-#ifdef CONFIG_PM
-	int (*pm_suspend)(struct poseidon *);
-	int (*pm_resume)(struct poseidon *);
-	pm_message_t		msg;
-
-	struct work_struct	pm_work;
-	u8			portnum;
-#endif
-};
-
-struct poseidon_format {
-	char 	*name;
-	int	fourcc;		 /* video4linux 2	  */
-	int	depth;		 /* bit/pixel		  */
-	int	flags;
-};
-
-struct poseidon_tvnorm {
-	v4l2_std_id	v4l2_id;
-	char		name[12];
-	u32		tlg_tvnorm;
-};
-
-/* video */
-int pd_video_init(struct poseidon *);
-void pd_video_exit(struct poseidon *);
-int stop_all_video_stream(struct poseidon *);
-
-/* alsa audio */
-int poseidon_audio_init(struct poseidon *);
-int poseidon_audio_free(struct poseidon *);
-#ifdef CONFIG_PM
-int pm_alsa_suspend(struct poseidon *);
-int pm_alsa_resume(struct poseidon *);
-#endif
-
-/* dvb */
-int pd_dvb_usb_device_init(struct poseidon *);
-void pd_dvb_usb_device_exit(struct poseidon *);
-void pd_dvb_usb_device_cleanup(struct poseidon *);
-int pd_dvb_get_adapter_num(struct pd_dvb_adapter *);
-void dvb_stop_streaming(struct pd_dvb_adapter *);
-
-/* FM */
-int poseidon_fm_init(struct poseidon *);
-int poseidon_fm_exit(struct poseidon *);
-
-/* vendor command ops */
-int send_set_req(struct poseidon*, u8, s32, s32*);
-int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
-s32 set_tuner_mode(struct poseidon*, unsigned char);
-
-/* bulk urb alloc/free */
-int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
-			struct usb_device *udev, u8 ep_addr,
-			int buf_size, gfp_t gfp_flags,
-			usb_complete_t complete_fn, void *context);
-void free_all_urb_generic(struct urb **urb_array, int num);
-
-/* misc */
-void poseidon_delete(struct kref *kref);
-extern int debug_mode;
-void set_debug_mode(struct video_device *vfd, int debug_mode);
-
-#ifdef CONFIG_PM
-#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE)
-#else
-#define in_hibernation(pd) (0)
-#endif
-#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt))
-
-#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \
-				__func__, __LINE__,  ## __VA_ARGS__)
-
-/* for power management */
-#define logpm(pd) do {\
-			if (debug_mode & 0x10)\
-				log();\
-		} while (0)
-
-#endif
diff --git a/drivers/staging/media/tlg2300/pd-dvb.c b/drivers/staging/media/tlg2300/pd-dvb.c
deleted file mode 100644
index ca4994a5190c..000000000000
--- a/drivers/staging/media/tlg2300/pd-dvb.c
+++ /dev/null
@@ -1,597 +0,0 @@
-#include "pd-common.h"
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/time.h>
-#include <linux/dvb/dmx.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-
-#include "vendorcmds.h"
-#include <linux/sched.h>
-#include <linux/atomic.h>
-
-static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
-
-static int dvb_bandwidth[][2] = {
-	{ TLG_BW_8, 8000000 },
-	{ TLG_BW_7, 7000000 },
-	{ TLG_BW_6, 6000000 }
-};
-static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth);
-
-static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb);
-static int poseidon_check_mode_dvbt(struct poseidon *pd)
-{
-	s32 ret = 0, cmd_status = 0;
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/4);
-
-	ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE);
-	if (ret != 0)
-		return ret;
-
-	ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T);
-	if (ret)
-		return ret;
-
-	/* signal source */
-	ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status);
-	if (ret|cmd_status)
-		return ret;
-
-	return 0;
-}
-
-/* acquire :
- * 	1 == open
- * 	0 == release
- */
-static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
-{
-	struct poseidon *pd = fe->demodulator_priv;
-	struct pd_dvb_adapter *pd_dvb;
-	int ret = 0;
-
-	if (!pd)
-		return -ENODEV;
-
-	pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe);
-	if (acquire) {
-		mutex_lock(&pd->lock);
-		if (pd->state & POSEIDON_STATE_DISCONNECT) {
-			ret = -ENODEV;
-			goto open_out;
-		}
-
-		if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) {
-			ret = -EBUSY;
-			goto open_out;
-		}
-
-		usb_autopm_get_interface(pd->interface);
-		if (0 == pd->state) {
-			ret = poseidon_check_mode_dvbt(pd);
-			if (ret < 0) {
-				usb_autopm_put_interface(pd->interface);
-				goto open_out;
-			}
-			pd->state |= POSEIDON_STATE_DVBT;
-			pd_dvb->bandwidth = 0;
-			pd_dvb->prev_freq = 0;
-		}
-		atomic_inc(&pd_dvb->users);
-		kref_get(&pd->kref);
-open_out:
-		mutex_unlock(&pd->lock);
-	} else {
-		dvb_stop_streaming(pd_dvb);
-
-		if (atomic_dec_and_test(&pd_dvb->users)) {
-			mutex_lock(&pd->lock);
-			pd->state &= ~POSEIDON_STATE_DVBT;
-			mutex_unlock(&pd->lock);
-		}
-		kref_put(&pd->kref, poseidon_delete);
-		usb_autopm_put_interface(pd->interface);
-	}
-	return ret;
-}
-
-#ifdef CONFIG_PM
-static void poseidon_fe_release(struct dvb_frontend *fe)
-{
-	struct poseidon *pd = fe->demodulator_priv;
-
-	pd->pm_suspend = NULL;
-	pd->pm_resume  = NULL;
-}
-#else
-#define poseidon_fe_release NULL
-#endif
-
-static s32 poseidon_fe_sleep(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-/*
- * return true if we can satisfy the conditions, else return false.
- */
-static bool check_scan_ok(__u32 freq, int bandwidth,
-			struct pd_dvb_adapter *adapter)
-{
-	if (bandwidth < 0)
-		return false;
-
-	if (adapter->prev_freq == freq
-		&& adapter->bandwidth == bandwidth) {
-		long nl = jiffies - adapter->last_jiffies;
-		unsigned int msec ;
-
-		msec = jiffies_to_msecs(abs(nl));
-		return msec > 15000 ? true : false;
-	}
-	return true;
-}
-
-/*
- * Check if the firmware delays too long for an invalid frequency.
- */
-static int fw_delay_overflow(struct pd_dvb_adapter *adapter)
-{
-	long nl = jiffies - adapter->last_jiffies;
-	unsigned int msec ;
-
-	msec = jiffies_to_msecs(abs(nl));
-	return msec > 800 ? true : false;
-}
-
-static int poseidon_set_fe(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	s32 ret = 0, cmd_status = 0;
-	s32 i, bandwidth = -1;
-	struct poseidon *pd = fe->demodulator_priv;
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-
-	if (in_hibernation(pd))
-		return -EBUSY;
-
-	mutex_lock(&pd->lock);
-	for (i = 0; i < dvb_bandwidth_length; i++)
-		if (fep->bandwidth_hz == dvb_bandwidth[i][1])
-			bandwidth = dvb_bandwidth[i][0];
-
-	if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) {
-		ret = send_set_req(pd, TUNE_FREQ_SELECT,
-					fep->frequency / 1000, &cmd_status);
-		if (ret | cmd_status) {
-			log("error line");
-			goto front_out;
-		}
-
-		ret = send_set_req(pd, DVBT_BANDW_SEL,
-						bandwidth, &cmd_status);
-		if (ret | cmd_status) {
-			log("error line");
-			goto front_out;
-		}
-
-		ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
-		if (ret | cmd_status) {
-			log("error line");
-			goto front_out;
-		}
-
-		/* save the context for future */
-		memcpy(&pd_dvb->fe_param, fep, sizeof(*fep));
-		pd_dvb->bandwidth = bandwidth;
-		pd_dvb->prev_freq = fep->frequency;
-		pd_dvb->last_jiffies = jiffies;
-	}
-front_out:
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-#ifdef CONFIG_PM
-static int pm_dvb_suspend(struct poseidon *pd)
-{
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-	dvb_stop_streaming(pd_dvb);
-	dvb_urb_cleanup(pd_dvb);
-	msleep(500);
-	return 0;
-}
-
-static int pm_dvb_resume(struct poseidon *pd)
-{
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-
-	poseidon_check_mode_dvbt(pd);
-	msleep(300);
-	poseidon_set_fe(&pd_dvb->dvb_fe);
-
-	dvb_start_streaming(pd_dvb);
-	return 0;
-}
-#endif
-
-static s32 poseidon_fe_init(struct dvb_frontend *fe)
-{
-	struct poseidon *pd = fe->demodulator_priv;
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-
-#ifdef CONFIG_PM
-	pd->pm_suspend = pm_dvb_suspend;
-	pd->pm_resume  = pm_dvb_resume;
-#endif
-	memset(&pd_dvb->fe_param, 0,
-			sizeof(struct dtv_frontend_properties));
-	return 0;
-}
-
-static int poseidon_get_fe(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct poseidon *pd = fe->demodulator_priv;
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-
-	memcpy(fep, &pd_dvb->fe_param, sizeof(*fep));
-	return 0;
-}
-
-static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe,
-				struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat)
-{
-	struct poseidon *pd = fe->demodulator_priv;
-	s32 ret = -1, cmd_status;
-	struct tuner_dtv_sig_stat_s status = {};
-
-	if (in_hibernation(pd))
-		return -EBUSY;
-	mutex_lock(&pd->lock);
-
-	ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
-				&status, &cmd_status, sizeof(status));
-	if (ret | cmd_status) {
-		log("get tuner status error");
-		goto out;
-	}
-
-	if (debug_mode)
-		log("P : %d, L %d, LB :%d", status.sig_present,
-			status.sig_locked, status.sig_lock_busy);
-
-	if (status.sig_lock_busy) {
-		goto out;
-	} else if (status.sig_present || status.sig_locked) {
-		*stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER
-				| FE_HAS_SYNC | FE_HAS_VITERBI;
-	} else {
-		if (fw_delay_overflow(&pd->dvb_data))
-			*stat |= FE_TIMEDOUT;
-	}
-out:
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct poseidon *pd = fe->demodulator_priv;
-	struct tuner_ber_rate_s tlg_ber = {};
-	s32 ret = -1, cmd_status;
-
-	mutex_lock(&pd->lock);
-	ret = send_get_req(pd, TUNER_BER_RATE, 0,
-				&tlg_ber, &cmd_status, sizeof(tlg_ber));
-	if (ret | cmd_status)
-		goto out;
-	*ber = tlg_ber.ber_rate;
-out:
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct poseidon *pd = fe->demodulator_priv;
-	struct tuner_dtv_sig_stat_s status = {};
-	s32 ret = 0, cmd_status;
-
-	mutex_lock(&pd->lock);
-	ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
-				&status, &cmd_status, sizeof(status));
-	if (ret | cmd_status)
-		goto out;
-	if ((status.sig_present || status.sig_locked) && !status.sig_strength)
-		*strength = 0xFFFF;
-	else
-		*strength = status.sig_strength;
-out:
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	return 0;
-}
-
-static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
-{
-	*unc = 0;
-	return 0;
-}
-
-static struct dvb_frontend_ops poseidon_frontend_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name		= "Poseidon DVB-T",
-		.frequency_min	= 174000000,
-		.frequency_max  = 862000000,
-		.frequency_stepsize	  = 62500,/* FIXME */
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = poseidon_fe_release,
-
-	.init = poseidon_fe_init,
-	.sleep = poseidon_fe_sleep,
-
-	.set_frontend = poseidon_set_fe,
-	.get_frontend = poseidon_get_fe,
-	.get_tune_settings = poseidon_fe_get_tune_settings,
-
-	.read_status	= poseidon_read_status,
-	.read_ber	= poseidon_read_ber,
-	.read_signal_strength = poseidon_read_signal_strength,
-	.read_snr	= poseidon_read_snr,
-	.read_ucblocks	= poseidon_read_unc_blocks,
-
-	.ts_bus_ctrl = poseidon_ts_bus_ctrl,
-};
-
-static void dvb_urb_irq(struct urb *urb)
-{
-	struct pd_dvb_adapter *pd_dvb = urb->context;
-	int len = urb->transfer_buffer_length;
-	struct dvb_demux *demux = &pd_dvb->demux;
-	s32 ret;
-
-	if (!pd_dvb->is_streaming || urb->status) {
-		if (urb->status == -EPROTO)
-			goto resend;
-		return;
-	}
-
-	if (urb->actual_length == len)
-		dvb_dmx_swfilter(demux, urb->transfer_buffer, len);
-	else if (urb->actual_length == len - 4) {
-		int offset;
-		u8 *buf = urb->transfer_buffer;
-
-		/*
-		 * The packet size is 512,
-		 * last packet contains 456 bytes tsp data
-		 */
-		for (offset = 456; offset < len; offset += 512) {
-			if (!strncmp(buf + offset, "DVHS", 4)) {
-				dvb_dmx_swfilter(demux, buf, offset);
-				if (len > offset + 52 + 4) {
-					/*16 bytes trailer + 36 bytes padding */
-					buf += offset + 52;
-					len -= offset + 52 + 4;
-					dvb_dmx_swfilter(demux, buf, len);
-				}
-				break;
-			}
-		}
-	}
-
-resend:
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret)
-		log(" usb_submit_urb failed: error %d", ret);
-}
-
-static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb)
-{
-	if (pd_dvb->urb_array[0])
-		return 0;
-
-	alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM,
-			pd_dvb->pd_device->udev, pd_dvb->ep_addr,
-			DVB_URB_BUF_SIZE, GFP_KERNEL,
-			dvb_urb_irq, pd_dvb);
-	return 0;
-}
-
-static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb)
-{
-	free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM);
-}
-
-static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb)
-{
-	struct poseidon *pd = pd_dvb->pd_device;
-	int ret = 0;
-
-	if (pd->state & POSEIDON_STATE_DISCONNECT)
-		return -ENODEV;
-
-	mutex_lock(&pd->lock);
-	if (!pd_dvb->is_streaming) {
-		s32 i, cmd_status = 0;
-		/*
-		 * Once upon a time, there was a difficult bug lying here.
-		 * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
-		 */
-
-		ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status);
-		if (ret | cmd_status)
-			goto out;
-
-		ret = dvb_urb_init(pd_dvb);
-		if (ret < 0)
-			goto out;
-
-		pd_dvb->is_streaming = 1;
-		for (i = 0; i < DVB_SBUF_NUM; i++) {
-			ret = usb_submit_urb(pd_dvb->urb_array[i],
-						       GFP_KERNEL);
-			if (ret) {
-				log(" submit urb error %d", ret);
-				goto out;
-			}
-		}
-	}
-out:
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb)
-{
-	struct poseidon *pd = pd_dvb->pd_device;
-
-	mutex_lock(&pd->lock);
-	if (pd_dvb->is_streaming) {
-		s32 i, ret, cmd_status = 0;
-
-		pd_dvb->is_streaming = 0;
-
-		for (i = 0; i < DVB_SBUF_NUM; i++)
-			if (pd_dvb->urb_array[i])
-				usb_kill_urb(pd_dvb->urb_array[i]);
-
-		ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
-					&cmd_status);
-		if (ret | cmd_status)
-			log("error");
-	}
-	mutex_unlock(&pd->lock);
-}
-
-static int pd_start_feed(struct dvb_demux_feed *feed)
-{
-	struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
-	int ret = 0;
-
-	if (!pd_dvb)
-		return -1;
-	if (atomic_inc_return(&pd_dvb->active_feed) == 1)
-		ret = dvb_start_streaming(pd_dvb);
-	return ret;
-}
-
-static int pd_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
-
-	if (!pd_dvb)
-		return -1;
-	if (atomic_dec_and_test(&pd_dvb->active_feed))
-		dvb_stop_streaming(pd_dvb);
-	return 0;
-}
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-int pd_dvb_usb_device_init(struct poseidon *pd)
-{
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-	struct dvb_demux *dvbdemux;
-	int ret = 0;
-
-	pd_dvb->ep_addr = 0x82;
-	atomic_set(&pd_dvb->users, 0);
-	atomic_set(&pd_dvb->active_feed, 0);
-	pd_dvb->pd_device = pd;
-
-	ret = dvb_register_adapter(&pd_dvb->dvb_adap,
-				"Poseidon dvbt adapter",
-				THIS_MODULE,
-				NULL /* for hibernation correctly*/,
-				adapter_nr);
-	if (ret < 0)
-		goto error1;
-
-	/* register frontend */
-	pd_dvb->dvb_fe.demodulator_priv = pd;
-	memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops,
-			sizeof(struct dvb_frontend_ops));
-	ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe);
-	if (ret < 0)
-		goto error2;
-
-	/* register demux device */
-	dvbdemux = &pd_dvb->demux;
-	dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-	dvbdemux->priv = pd_dvb;
-	dvbdemux->feednum = dvbdemux->filternum = 64;
-	dvbdemux->start_feed = pd_start_feed;
-	dvbdemux->stop_feed = pd_stop_feed;
-	dvbdemux->write_to_decoder = NULL;
-
-	ret = dvb_dmx_init(dvbdemux);
-	if (ret < 0)
-		goto error3;
-
-	pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum;
-	pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx;
-	pd_dvb->dmxdev.capabilities = 0;
-
-	ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap);
-	if (ret < 0)
-		goto error3;
-	return 0;
-
-error3:
-	dvb_unregister_frontend(&pd_dvb->dvb_fe);
-error2:
-	dvb_unregister_adapter(&pd_dvb->dvb_adap);
-error1:
-	return ret;
-}
-
-void pd_dvb_usb_device_exit(struct poseidon *pd)
-{
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-
-	while (atomic_read(&pd_dvb->users) != 0
-		|| atomic_read(&pd_dvb->active_feed) != 0) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ);
-	}
-	dvb_dmxdev_release(&pd_dvb->dmxdev);
-	dvb_unregister_frontend(&pd_dvb->dvb_fe);
-	dvb_unregister_adapter(&pd_dvb->dvb_adap);
-	pd_dvb_usb_device_cleanup(pd);
-}
-
-void pd_dvb_usb_device_cleanup(struct poseidon *pd)
-{
-	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
-
-	dvb_urb_cleanup(pd_dvb);
-}
-
-int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb)
-{
-	return pd_dvb->dvb_adap.num;
-}
diff --git a/drivers/staging/media/tlg2300/pd-main.c b/drivers/staging/media/tlg2300/pd-main.c
deleted file mode 100644
index b31f4791b8ff..000000000000
--- a/drivers/staging/media/tlg2300/pd-main.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * device driver for Telegent tlg2300 based TV cards
- *
- * Author :
- * 	Kang Yong	<kangyong@telegent.com>
- * 	Zhang Xiaobing	<xbzhang@telegent.com>
- * 	Huang Shijie	<zyziii@telegent.com> or <shijie8@gmail.com>
- *
- *	(c) 2009 Telegent Systems
- *	(c) 2010 Telegent Systems
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/suspend.h>
-#include <linux/usb/quirks.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/firmware.h>
-
-#include "vendorcmds.h"
-#include "pd-common.h"
-
-#define VENDOR_ID	0x1B24
-#define PRODUCT_ID	0x4001
-static struct usb_device_id id_table[] = {
-	{ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) },
-	{ },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-int debug_mode;
-module_param(debug_mode, int, 0644);
-MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose");
-
-#define TLG2300_FIRMWARE "tlg2300_firmware.bin"
-static const char *firmware_name = TLG2300_FIRMWARE;
-static LIST_HEAD(pd_device_list);
-
-/*
- * send set request to USB firmware.
- */
-s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status)
-{
-	s32 ret;
-	s8  data[32] = {};
-	u16 lower_16, upper_16;
-
-	if (pd->state & POSEIDON_STATE_DISCONNECT)
-		return -ENODEV;
-
-	mdelay(30);
-
-	if (param == 0) {
-		upper_16 = lower_16 = 0;
-	} else {
-		/* send 32 bit param as  two 16 bit param,little endian */
-		lower_16 = (unsigned short)(param & 0xffff);
-		upper_16 = (unsigned short)((param >> 16) & 0xffff);
-	}
-	ret = usb_control_msg(pd->udev,
-			 usb_rcvctrlpipe(pd->udev, 0),
-			 REQ_SET_CMD | cmdid,
-			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			 lower_16,
-			 upper_16,
-			 &data,
-			 sizeof(*cmd_status),
-			 USB_CTRL_GET_TIMEOUT);
-
-	if (!ret) {
-		return -ENXIO;
-	} else {
-		/*  1st 4 bytes into cmd_status   */
-		memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status));
-	}
-	return 0;
-}
-
-/*
- * send get request to Poseidon firmware.
- */
-s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param,
-			void *buf, s32 *cmd_status, s32 datalen)
-{
-	s32 ret;
-	s8 data[128] = {};
-	u16 lower_16, upper_16;
-
-	if (pd->state & POSEIDON_STATE_DISCONNECT)
-		return -ENODEV;
-
-	mdelay(30);
-	if (param == 0) {
-		upper_16 = lower_16 = 0;
-	} else {
-		/*send 32 bit param as two 16 bit param, little endian */
-		lower_16 = (unsigned short)(param & 0xffff);
-		upper_16 = (unsigned short)((param >> 16) & 0xffff);
-	}
-	ret = usb_control_msg(pd->udev,
-			 usb_rcvctrlpipe(pd->udev, 0),
-			 REQ_GET_CMD | cmdid,
-			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			 lower_16,
-			 upper_16,
-			 &data,
-			 (datalen + sizeof(*cmd_status)),
-			 USB_CTRL_GET_TIMEOUT);
-
-	if (ret < 0) {
-		return -ENXIO;
-	} else {
-		/* 1st 4 bytes into cmd_status, remaining data into cmd_data */
-		memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status));
-		memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen);
-	}
-	return 0;
-}
-
-static int pm_notifier_block(struct notifier_block *nb,
-				unsigned long event, void *dummy)
-{
-	struct poseidon *pd = NULL;
-	struct list_head *node, *next;
-
-	switch (event) {
-	case PM_POST_HIBERNATION:
-		list_for_each_safe(node, next, &pd_device_list) {
-			struct usb_device *udev;
-			struct usb_interface *iface;
-			int rc = 0;
-
-			pd = container_of(node, struct poseidon, device_list);
-			udev = pd->udev;
-			iface = pd->interface;
-
-			/* It will cause the system to reload the firmware */
-			rc = usb_lock_device_for_reset(udev, iface);
-			if (rc >= 0) {
-				usb_reset_device(udev);
-				usb_unlock_device(udev);
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	log("event :%ld\n", event);
-	return 0;
-}
-
-static struct notifier_block pm_notifer = {
-	.notifier_call = pm_notifier_block,
-};
-
-int set_tuner_mode(struct poseidon *pd, unsigned char mode)
-{
-	s32 ret, cmd_status;
-
-	if (pd->state & POSEIDON_STATE_DISCONNECT)
-		return -ENODEV;
-
-	ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status);
-	if (ret || cmd_status)
-		return -ENXIO;
-	return 0;
-}
-
-void poseidon_delete(struct kref *kref)
-{
-	struct poseidon *pd = container_of(kref, struct poseidon, kref);
-
-	if (!pd)
-		return;
-	list_del_init(&pd->device_list);
-
-	pd_dvb_usb_device_cleanup(pd);
-	/* clean_audio_data(&pd->audio_data);*/
-
-	if (pd->udev) {
-		usb_put_dev(pd->udev);
-		pd->udev = NULL;
-	}
-	if (pd->interface) {
-		usb_put_intf(pd->interface);
-		pd->interface = NULL;
-	}
-	kfree(pd);
-	log();
-}
-
-static int firmware_download(struct usb_device *udev)
-{
-	int ret = 0, actual_length;
-	const struct firmware *fw = NULL;
-	void *fwbuf = NULL;
-	size_t fwlength = 0, offset;
-	size_t max_packet_size;
-
-	ret = request_firmware(&fw, firmware_name, &udev->dev);
-	if (ret) {
-		log("download err : %d", ret);
-		return ret;
-	}
-
-	fwlength = fw->size;
-
-	fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL);
-	if (!fwbuf) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	max_packet_size = le16_to_cpu(udev->ep_out[0x1]->desc.wMaxPacketSize);
-	log("\t\t download size : %d", (int)max_packet_size);
-
-	for (offset = 0; offset < fwlength; offset += max_packet_size) {
-		actual_length = 0;
-		ret = usb_bulk_msg(udev,
-				usb_sndbulkpipe(udev, 0x01), /* ep 1 */
-				fwbuf + offset,
-				min(max_packet_size, fwlength - offset),
-				&actual_length,
-				HZ * 10);
-		if (ret)
-			break;
-	}
-	kfree(fwbuf);
-out:
-	release_firmware(fw);
-	return ret;
-}
-
-static inline struct poseidon *get_pd(struct usb_interface *intf)
-{
-	return usb_get_intfdata(intf);
-}
-
-#ifdef CONFIG_PM
-/* one-to-one map : poseidon{} <----> usb_device{}'s port */
-static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
-{
-	pd->portnum = udev->portnum;
-}
-
-static inline int get_autopm_ref(struct poseidon *pd)
-{
-	return  pd->video_data.users + pd->vbi_data.users + pd->audio.users
-		+ atomic_read(&pd->dvb_data.users) +
-		!list_empty(&pd->radio_data.fm_dev.fh_list);
-}
-
-/* fixup something for poseidon */
-static inline struct poseidon *fixup(struct poseidon *pd)
-{
-	int count;
-
-	/* old udev and interface have gone, so put back reference . */
-	count = get_autopm_ref(pd);
-	log("count : %d, ref count : %d", count, get_pm_count(pd));
-	while (count--)
-		usb_autopm_put_interface(pd->interface);
-	/*usb_autopm_set_interface(pd->interface); */
-
-	usb_put_dev(pd->udev);
-	usb_put_intf(pd->interface);
-	log("event : %d\n", pd->msg.event);
-	return pd;
-}
-
-static struct poseidon *find_old_poseidon(struct usb_device *udev)
-{
-	struct poseidon *pd;
-
-	list_for_each_entry(pd, &pd_device_list, device_list) {
-		if (pd->portnum == udev->portnum && in_hibernation(pd))
-			return fixup(pd);
-	}
-	return NULL;
-}
-
-/* Is the card working now ? */
-static inline int is_working(struct poseidon *pd)
-{
-	return get_pm_count(pd) > 0;
-}
-
-static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg)
-{
-	struct poseidon *pd = get_pd(intf);
-
-	if (!pd)
-		return 0;
-	if (!is_working(pd)) {
-		if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) {
-			pd->msg.event = PM_EVENT_AUTO_SUSPEND;
-			pd->pm_resume = NULL; /*  a good guard */
-			printk(KERN_DEBUG "TLG2300 auto suspend\n");
-		}
-		return 0;
-	}
-	pd->msg = msg; /* save it here */
-	logpm(pd);
-	return pd->pm_suspend ? pd->pm_suspend(pd) : 0;
-}
-
-static int poseidon_resume(struct usb_interface *intf)
-{
-	struct poseidon *pd = get_pd(intf);
-
-	if (!pd)
-		return 0;
-	printk(KERN_DEBUG "TLG2300 resume\n");
-
-	if (!is_working(pd)) {
-		if (PM_EVENT_AUTO_SUSPEND == pd->msg.event)
-			pd->msg = PMSG_ON;
-		return 0;
-	}
-	if (in_hibernation(pd)) {
-		logpm(pd);
-		return 0;
-	}
-	logpm(pd);
-	return pd->pm_resume ? pd->pm_resume(pd) : 0;
-}
-
-static void hibernation_resume(struct work_struct *w)
-{
-	struct poseidon *pd = container_of(w, struct poseidon, pm_work);
-	int count;
-
-	pd->msg.event = 0; /* clear it here */
-	pd->state &= ~POSEIDON_STATE_DISCONNECT;
-
-	/* set the new interface's reference */
-	count = get_autopm_ref(pd);
-	while (count--)
-		usb_autopm_get_interface(pd->interface);
-
-	/* resume the context */
-	logpm(pd);
-	if (pd->pm_resume)
-		pd->pm_resume(pd);
-}
-#else /* CONFIG_PM is not enabled: */
-static inline struct poseidon *find_old_poseidon(struct usb_device *udev)
-{
-	return NULL;
-}
-
-static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
-{
-}
-#endif
-
-static int check_firmware(struct usb_device *udev)
-{
-	void *buf;
-	int ret;
-	struct cmd_firmware_vers_s *cmd_firm;
-
-	buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	ret = usb_control_msg(udev,
-			 usb_rcvctrlpipe(udev, 0),
-			 REQ_GET_CMD | GET_FW_ID,
-			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			 0,
-			 0,
-			 buf,
-			 sizeof(*cmd_firm) + sizeof(u32),
-			 USB_CTRL_GET_TIMEOUT);
-	kfree(buf);
-
-	if (ret < 0)
-		return firmware_download(udev);
-	return 0;
-}
-
-static int poseidon_probe(struct usb_interface *interface,
-				const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct poseidon *pd = NULL;
-	int ret = 0;
-	int new_one = 0;
-
-	/* download firmware */
-	ret = check_firmware(udev);
-	if (ret)
-		return ret;
-
-	/* Do I recovery from the hibernate ? */
-	pd = find_old_poseidon(udev);
-	if (!pd) {
-		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
-		if (!pd)
-			return -ENOMEM;
-		kref_init(&pd->kref);
-		set_map_flags(pd, udev);
-		new_one = 1;
-	}
-
-	pd->udev	= usb_get_dev(udev);
-	pd->interface	= usb_get_intf(interface);
-	usb_set_intfdata(interface, pd);
-
-	if (new_one) {
-		logpm(pd);
-		mutex_init(&pd->lock);
-
-		/* register v4l2 device */
-		ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev);
-		if (ret)
-			goto err_v4l2;
-
-		/* register devices in directory /dev */
-		ret = pd_video_init(pd);
-		if (ret)
-			goto err_video;
-		ret = poseidon_audio_init(pd);
-		if (ret)
-			goto err_audio;
-		ret = poseidon_fm_init(pd);
-		if (ret)
-			goto err_fm;
-		ret = pd_dvb_usb_device_init(pd);
-		if (ret)
-			goto err_dvb;
-
-		INIT_LIST_HEAD(&pd->device_list);
-		list_add_tail(&pd->device_list, &pd_device_list);
-	}
-
-	device_init_wakeup(&udev->dev, 1);
-#ifdef CONFIG_PM
-	pm_runtime_set_autosuspend_delay(&pd->udev->dev,
-			1000 * PM_SUSPEND_DELAY);
-	usb_enable_autosuspend(pd->udev);
-
-	if (in_hibernation(pd)) {
-		INIT_WORK(&pd->pm_work, hibernation_resume);
-		schedule_work(&pd->pm_work);
-	}
-#endif
-	return 0;
-err_dvb:
-	poseidon_fm_exit(pd);
-err_fm:
-	poseidon_audio_free(pd);
-err_audio:
-	pd_video_exit(pd);
-err_video:
-	v4l2_device_unregister(&pd->v4l2_dev);
-err_v4l2:
-	usb_put_intf(pd->interface);
-	usb_put_dev(pd->udev);
-	kfree(pd);
-	return ret;
-}
-
-static void poseidon_disconnect(struct usb_interface *interface)
-{
-	struct poseidon *pd = get_pd(interface);
-
-	if (!pd)
-		return;
-	logpm(pd);
-	if (in_hibernation(pd))
-		return;
-
-	mutex_lock(&pd->lock);
-	pd->state |= POSEIDON_STATE_DISCONNECT;
-	mutex_unlock(&pd->lock);
-
-	/* stop urb transferring */
-	stop_all_video_stream(pd);
-	dvb_stop_streaming(&pd->dvb_data);
-
-	/*unregister v4l2 device */
-	v4l2_device_unregister(&pd->v4l2_dev);
-
-	pd_dvb_usb_device_exit(pd);
-	poseidon_fm_exit(pd);
-
-	poseidon_audio_free(pd);
-	pd_video_exit(pd);
-
-	usb_set_intfdata(interface, NULL);
-	kref_put(&pd->kref, poseidon_delete);
-}
-
-static struct usb_driver poseidon_driver = {
-	.name		= "poseidon",
-	.probe		= poseidon_probe,
-	.disconnect	= poseidon_disconnect,
-	.id_table	= id_table,
-#ifdef CONFIG_PM
-	.suspend	= poseidon_suspend,
-	.resume		= poseidon_resume,
-#endif
-	.supports_autosuspend = 1,
-};
-
-static int __init poseidon_init(void)
-{
-	int ret;
-
-	ret = usb_register(&poseidon_driver);
-	if (ret)
-		return ret;
-	register_pm_notifier(&pm_notifer);
-	return ret;
-}
-
-static void __exit poseidon_exit(void)
-{
-	log();
-	unregister_pm_notifier(&pm_notifer);
-	usb_deregister(&poseidon_driver);
-}
-
-module_init(poseidon_init);
-module_exit(poseidon_exit);
-
-MODULE_AUTHOR("Telegent Systems");
-MODULE_DESCRIPTION("For tlg2300-based USB device");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.2");
-MODULE_FIRMWARE(TLG2300_FIRMWARE);
diff --git a/drivers/staging/media/tlg2300/pd-radio.c b/drivers/staging/media/tlg2300/pd-radio.c
deleted file mode 100644
index b391194a840c..000000000000
--- a/drivers/staging/media/tlg2300/pd-radio.c
+++ /dev/null
@@ -1,339 +0,0 @@
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bitmap.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <media/v4l2-dev.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-fh.h>
-#include <linux/sched.h>
-
-#include "pd-common.h"
-#include "vendorcmds.h"
-
-static int set_frequency(struct poseidon *p, __u32 frequency);
-static int poseidon_fm_close(struct file *filp);
-static int poseidon_fm_open(struct file *filp);
-
-#define TUNER_FREQ_MIN_FM 76000000U
-#define TUNER_FREQ_MAX_FM 108000000U
-
-#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1)
-static int preemphasis[MAX_PREEMPHASIS] = {
-	TLG_TUNE_ASTD_NONE,   /* V4L2_PREEMPHASIS_DISABLED */
-	TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS    */
-	TLG_TUNE_ASTD_FM_US,  /* V4L2_PREEMPHASIS_75_uS    */
-};
-
-static int poseidon_check_mode_radio(struct poseidon *p)
-{
-	int ret;
-	u32 status;
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/2);
-	ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE);
-	if (ret < 0)
-		goto out;
-
-	ret = set_tuner_mode(p, TLG_MODE_FM_RADIO);
-	if (ret != 0)
-		goto out;
-
-	ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status);
-	ret = send_set_req(p, TUNER_AUD_ANA_STD,
-				p->radio_data.pre_emphasis, &status);
-	ret |= send_set_req(p, TUNER_AUD_MODE,
-				TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
-	ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL,
-				ATV_AUDIO_RATE_48K, &status);
-	ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status);
-out:
-	return ret;
-}
-
-#ifdef CONFIG_PM
-static int pm_fm_suspend(struct poseidon *p)
-{
-	logpm(p);
-	pm_alsa_suspend(p);
-	usb_set_interface(p->udev, 0, 0);
-	msleep(300);
-	return 0;
-}
-
-static int pm_fm_resume(struct poseidon *p)
-{
-	logpm(p);
-	poseidon_check_mode_radio(p);
-	set_frequency(p, p->radio_data.fm_freq);
-	pm_alsa_resume(p);
-	return 0;
-}
-#endif
-
-static int poseidon_fm_open(struct file *filp)
-{
-	struct poseidon *p = video_drvdata(filp);
-	int ret = 0;
-
-	mutex_lock(&p->lock);
-	if (p->state & POSEIDON_STATE_DISCONNECT) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	if (p->state && !(p->state & POSEIDON_STATE_FM)) {
-		ret = -EBUSY;
-		goto out;
-	}
-	ret = v4l2_fh_open(filp);
-	if (ret)
-		goto out;
-
-	usb_autopm_get_interface(p->interface);
-	if (0 == p->state) {
-		struct video_device *vfd = &p->radio_data.fm_dev;
-
-		/* default pre-emphasis */
-		if (p->radio_data.pre_emphasis == 0)
-			p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
-		set_debug_mode(vfd, debug_mode);
-
-		ret = poseidon_check_mode_radio(p);
-		if (ret < 0) {
-			usb_autopm_put_interface(p->interface);
-			goto out;
-		}
-		p->state |= POSEIDON_STATE_FM;
-	}
-	kref_get(&p->kref);
-out:
-	mutex_unlock(&p->lock);
-	return ret;
-}
-
-static int poseidon_fm_close(struct file *filp)
-{
-	struct poseidon *p = video_drvdata(filp);
-	struct radio_data *fm = &p->radio_data;
-	uint32_t status;
-
-	mutex_lock(&p->lock);
-	if (v4l2_fh_is_singular_file(filp))
-		p->state &= ~POSEIDON_STATE_FM;
-
-	if (fm->is_radio_streaming && filp == p->file_for_stream) {
-		fm->is_radio_streaming = 0;
-		send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status);
-	}
-	usb_autopm_put_interface(p->interface);
-	mutex_unlock(&p->lock);
-
-	kref_put(&p->kref, poseidon_delete);
-	return v4l2_fh_release(filp);
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-			struct v4l2_capability *v)
-{
-	struct poseidon *p = video_drvdata(file);
-
-	strlcpy(v->driver, "tele-radio", sizeof(v->driver));
-	strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
-	usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
-	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-	/* Report all capabilities of the USB device */
-	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS |
-			V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
-			V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
-			V4L2_CAP_READWRITE;
-	return 0;
-}
-
-static const struct v4l2_file_operations poseidon_fm_fops = {
-	.owner         = THIS_MODULE,
-	.open          = poseidon_fm_open,
-	.release       = poseidon_fm_close,
-	.poll		= v4l2_ctrl_poll,
-	.unlocked_ioctl = video_ioctl2,
-};
-
-static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
-				 struct v4l2_tuner *vt)
-{
-	struct poseidon *p = video_drvdata(file);
-	struct tuner_fm_sig_stat_s fm_stat = {};
-	int ret, status, count = 5;
-
-	if (vt->index != 0)
-		return -EINVAL;
-
-	vt->type	= V4L2_TUNER_RADIO;
-	vt->capability	= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
-	vt->rangelow	= TUNER_FREQ_MIN_FM * 2 / 125;
-	vt->rangehigh	= TUNER_FREQ_MAX_FM * 2 / 125;
-	vt->rxsubchans	= V4L2_TUNER_SUB_STEREO;
-	vt->audmode	= V4L2_TUNER_MODE_STEREO;
-	vt->signal	= 0;
-	vt->afc 	= 0;
-	strlcpy(vt->name, "Radio", sizeof(vt->name));
-
-	mutex_lock(&p->lock);
-	ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
-			      &fm_stat, &status, sizeof(fm_stat));
-
-	while (fm_stat.sig_lock_busy && count-- && !ret) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ);
-
-		ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
-				  &fm_stat, &status, sizeof(fm_stat));
-	}
-	mutex_unlock(&p->lock);
-
-	if (ret || status) {
-		vt->signal = 0;
-	} else if ((fm_stat.sig_present || fm_stat.sig_locked)
-			&& fm_stat.sig_strength == 0) {
-		vt->signal = 0xffff;
-	} else
-		vt->signal = (fm_stat.sig_strength * 255 / 10) << 8;
-
-	return 0;
-}
-
-static int fm_get_freq(struct file *file, void *priv,
-		       struct v4l2_frequency *argp)
-{
-	struct poseidon *p = video_drvdata(file);
-
-	if (argp->tuner)
-		return -EINVAL;
-	argp->frequency = p->radio_data.fm_freq;
-	return 0;
-}
-
-static int set_frequency(struct poseidon *p, __u32 frequency)
-{
-	__u32 freq ;
-	int ret, status;
-
-	mutex_lock(&p->lock);
-
-	ret = send_set_req(p, TUNER_AUD_ANA_STD,
-				p->radio_data.pre_emphasis, &status);
-
-	freq = (frequency * 125) / 2; /* Hz */
-	freq = clamp(freq, TUNER_FREQ_MIN_FM, TUNER_FREQ_MAX_FM);
-
-	ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status);
-	if (ret < 0)
-		goto error ;
-	ret = send_set_req(p, TAKE_REQUEST, 0, &status);
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/4);
-	if (!p->radio_data.is_radio_streaming) {
-		ret = send_set_req(p, TAKE_REQUEST, 0, &status);
-		ret = send_set_req(p, PLAY_SERVICE,
-				TLG_TUNE_PLAY_SVC_START, &status);
-		p->radio_data.is_radio_streaming = 1;
-	}
-	p->radio_data.fm_freq = freq * 2 / 125;
-error:
-	mutex_unlock(&p->lock);
-	return ret;
-}
-
-static int fm_set_freq(struct file *file, void *priv,
-		       const struct v4l2_frequency *argp)
-{
-	struct poseidon *p = video_drvdata(file);
-
-	if (argp->tuner)
-		return -EINVAL;
-	p->file_for_stream = file;
-#ifdef CONFIG_PM
-	p->pm_suspend = pm_fm_suspend;
-	p->pm_resume  = pm_fm_resume;
-#endif
-	return set_frequency(p, argp->frequency);
-}
-
-static int tlg_fm_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct poseidon *p = container_of(ctrl->handler, struct poseidon,
-						radio_data.ctrl_handler);
-	int pre_emphasis;
-	u32 status;
-
-	switch (ctrl->id) {
-	case V4L2_CID_TUNE_PREEMPHASIS:
-		pre_emphasis = preemphasis[ctrl->val];
-		send_set_req(p, TUNER_AUD_ANA_STD, pre_emphasis, &status);
-		p->radio_data.pre_emphasis = pre_emphasis;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
-{
-	return vt->index > 0 ? -EINVAL : 0;
-}
-
-static const struct v4l2_ctrl_ops tlg_fm_ctrl_ops = {
-	.s_ctrl = tlg_fm_s_ctrl,
-};
-
-static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
-	.vidioc_querycap    = vidioc_querycap,
-	.vidioc_s_tuner     = vidioc_s_tuner,
-	.vidioc_g_tuner     = tlg_fm_vidioc_g_tuner,
-	.vidioc_g_frequency = fm_get_freq,
-	.vidioc_s_frequency = fm_set_freq,
-	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static struct video_device poseidon_fm_template = {
-	.name       = "Telegent-Radio",
-	.fops       = &poseidon_fm_fops,
-	.minor      = -1,
-	.release    = video_device_release_empty,
-	.ioctl_ops  = &poseidon_fm_ioctl_ops,
-};
-
-int poseidon_fm_init(struct poseidon *p)
-{
-	struct video_device *vfd = &p->radio_data.fm_dev;
-	struct v4l2_ctrl_handler *hdl = &p->radio_data.ctrl_handler;
-
-	*vfd = poseidon_fm_template;
-
-	set_frequency(p, TUNER_FREQ_MIN_FM);
-	v4l2_ctrl_handler_init(hdl, 1);
-	v4l2_ctrl_new_std_menu(hdl, &tlg_fm_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
-			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
-	if (hdl->error) {
-		v4l2_ctrl_handler_free(hdl);
-		return hdl->error;
-	}
-	vfd->v4l2_dev = &p->v4l2_dev;
-	vfd->ctrl_handler = hdl;
-	video_set_drvdata(vfd, p);
-	return video_register_device(vfd, VFL_TYPE_RADIO, -1);
-}
-
-int poseidon_fm_exit(struct poseidon *p)
-{
-	video_unregister_device(&p->radio_data.fm_dev);
-	v4l2_ctrl_handler_free(&p->radio_data.ctrl_handler);
-	return 0;
-}
diff --git a/drivers/staging/media/tlg2300/pd-video.c b/drivers/staging/media/tlg2300/pd-video.c
deleted file mode 100644
index 8cd7f02fcf9f..000000000000
--- a/drivers/staging/media/tlg2300/pd-video.c
+++ /dev/null
@@ -1,1570 +0,0 @@
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/videodev2.h>
-#include <linux/usb.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-ctrls.h>
-
-#include "pd-common.h"
-#include "vendorcmds.h"
-
-#ifdef CONFIG_PM
-static int pm_video_suspend(struct poseidon *pd);
-static int pm_video_resume(struct poseidon *pd);
-#endif
-static void iso_bubble_handler(struct work_struct *w);
-
-static int usb_transfer_mode;
-module_param(usb_transfer_mode, int, 0644);
-MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous");
-
-static const struct poseidon_format poseidon_formats[] = {
-	{ "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0},
-	{ "RGB565", V4L2_PIX_FMT_RGB565, 16, 0},
-};
-
-static const struct poseidon_tvnorm poseidon_tvnorms[] = {
-	{ V4L2_STD_PAL_D, "PAL-D",  TLG_TUNE_VSTD_PAL_D },
-	{ V4L2_STD_PAL_B, "PAL-B",  TLG_TUNE_VSTD_PAL_B },
-	{ V4L2_STD_PAL_G, "PAL-G",  TLG_TUNE_VSTD_PAL_G },
-	{ V4L2_STD_PAL_H, "PAL-H",  TLG_TUNE_VSTD_PAL_H },
-	{ V4L2_STD_PAL_I, "PAL-I",  TLG_TUNE_VSTD_PAL_I },
-	{ V4L2_STD_PAL_M, "PAL-M",  TLG_TUNE_VSTD_PAL_M },
-	{ V4L2_STD_PAL_N, "PAL-N",  TLG_TUNE_VSTD_PAL_N_COMBO },
-	{ V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO },
-	{ V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M },
-	{ V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J },
-	{ V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B },
-	{ V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D },
-	{ V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G },
-	{ V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H },
-	{ V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K },
-	{ V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 },
-	{ V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L },
-	{ V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 },
-};
-static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms);
-
-struct pd_audio_mode {
-	u32 tlg_audio_mode;
-	u32 v4l2_audio_sub;
-	u32 v4l2_audio_mode;
-};
-
-static const struct pd_audio_mode pd_audio_modes[] = {
-	{ TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO,
-		V4L2_TUNER_MODE_MONO },
-	{ TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO,
-		V4L2_TUNER_MODE_STEREO },
-	{ TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1,
-		V4L2_TUNER_MODE_LANG1 },
-	{ TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2,
-		V4L2_TUNER_MODE_LANG2 },
-	{ TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1,
-		V4L2_TUNER_MODE_LANG1_LANG2 }
-};
-static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes);
-
-struct pd_input {
-	char *name;
-	uint32_t tlg_src;
-};
-
-static const struct pd_input pd_inputs[] = {
-	{ "TV Antenna", TLG_SIG_SRC_ANTENNA },
-	{ "TV Cable", TLG_SIG_SRC_CABLE },
-	{ "TV SVideo", TLG_SIG_SRC_SVIDEO },
-	{ "TV Composite", TLG_SIG_SRC_COMPOSITE }
-};
-static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs);
-
-struct video_std_to_audio_std {
-	v4l2_std_id	video_std;
-	int 		audio_std;
-};
-
-static const struct video_std_to_audio_std video_to_audio_map[] = {
-	/* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64,
-			65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */
-	{ (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D |
-		V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM },
-
-	/* country : { 1, 52, 54, 55, 886 } */
-	{V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC},
-
-	/* country : { 81 } */
-	{ V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ },
-
-	/* other country : TLG_TUNE_ASTD_A2 */
-};
-static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map);
-
-static int get_audio_std(v4l2_std_id v4l2_std)
-{
-	int i = 0;
-
-	for (; i < map_size; i++) {
-		if (v4l2_std & video_to_audio_map[i].video_std)
-			return video_to_audio_map[i].audio_std;
-	}
-	return TLG_TUNE_ASTD_A2;
-}
-
-static int vidioc_querycap(struct file *file, void *fh,
-			struct v4l2_capability *cap)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct poseidon *p = video_get_drvdata(vdev);
-
-	strcpy(cap->driver, "tele-video");
-	strcpy(cap->card, "Telegent Poseidon");
-	usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
-	cap->device_caps = V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
-			V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
-	if (vdev->vfl_type == VFL_TYPE_VBI)
-		cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
-	else
-		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
-		V4L2_CAP_RADIO | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
-	return 0;
-}
-
-/*====================================================================*/
-static void init_copy(struct video_data *video, bool index)
-{
-	struct front_face *front = video->front;
-
-	video->field_count	= index;
-	video->lines_copied	= 0;
-	video->prev_left	= 0 ;
-	video->dst 		= (char *)videobuf_to_vmalloc(front->curr_frame)
-					+ index * video->lines_size;
-	video->vbi->copied 	= 0; /* set it here */
-}
-
-static bool get_frame(struct front_face *front, int *need_init)
-{
-	struct videobuf_buffer *vb = front->curr_frame;
-
-	if (vb)
-		return true;
-
-	spin_lock(&front->queue_lock);
-	if (!list_empty(&front->active)) {
-		vb = list_entry(front->active.next,
-			       struct videobuf_buffer, queue);
-		if (need_init)
-			*need_init = 1;
-		front->curr_frame = vb;
-		list_del_init(&vb->queue);
-	}
-	spin_unlock(&front->queue_lock);
-
-	return !!vb;
-}
-
-/* check if the video's buffer is ready */
-static bool get_video_frame(struct front_face *front, struct video_data *video)
-{
-	int need_init = 0;
-	bool ret = true;
-
-	ret = get_frame(front, &need_init);
-	if (ret && need_init)
-		init_copy(video, 0);
-	return ret;
-}
-
-static void submit_frame(struct front_face *front)
-{
-	struct videobuf_buffer *vb = front->curr_frame;
-
-	if (vb == NULL)
-		return;
-
-	front->curr_frame	= NULL;
-	vb->state		= VIDEOBUF_DONE;
-	vb->field_count++;
-	v4l2_get_timestamp(&vb->ts);
-
-	wake_up(&vb->done);
-}
-
-/*
- * A frame is composed of two fields. If we receive all the two fields,
- * call the  submit_frame() to submit the whole frame to applications.
- */
-static void end_field(struct video_data *video)
-{
-	if (1 == video->field_count)
-		submit_frame(video->front);
-	else
-		init_copy(video, 1);
-}
-
-static void copy_video_data(struct video_data *video, char *src,
-				unsigned int count)
-{
-#define copy_data(len)  \
-	do { \
-		if (++video->lines_copied > video->lines_per_field) \
-			goto overflow; \
-		memcpy(video->dst, src, len);\
-		video->dst += len + video->lines_size; \
-		src += len; \
-		count -= len; \
-	 } while (0)
-
-	while (count && count >= video->lines_size) {
-		if (video->prev_left) {
-			copy_data(video->prev_left);
-			video->prev_left = 0;
-			continue;
-		}
-		copy_data(video->lines_size);
-	}
-	if (count && count < video->lines_size) {
-		memcpy(video->dst, src, count);
-
-		video->prev_left = video->lines_size - count;
-		video->dst += count;
-	}
-	return;
-
-overflow:
-	end_field(video);
-}
-
-static void check_trailer(struct video_data *video, char *src, int count)
-{
-	struct vbi_data *vbi = video->vbi;
-	int offset; /* trailer's offset */
-	char *buf;
-
-	offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2)
-		- (vbi->copied + video->lines_size * video->lines_copied);
-	if (video->prev_left)
-		offset -= (video->lines_size - video->prev_left);
-
-	if (offset > count || offset <= 0)
-		goto short_package;
-
-	buf = src + offset;
-
-	/* trailer : (VFHS) + U32 + U32 + field_num */
-	if (!strncmp(buf, "VFHS", 4)) {
-		int field_num = *((u32 *)(buf + 12));
-
-		if ((field_num & 1) ^ video->field_count) {
-			init_copy(video, video->field_count);
-			return;
-		}
-		copy_video_data(video, src, offset);
-	}
-short_package:
-	end_field(video);
-}
-
-/* ==========  Check this more carefully! =========== */
-static inline void copy_vbi_data(struct vbi_data *vbi,
-				char *src, unsigned int count)
-{
-	struct front_face *front = vbi->front;
-
-	if (front && get_frame(front, NULL)) {
-		char *buf = videobuf_to_vmalloc(front->curr_frame);
-
-		if (vbi->video->field_count)
-			buf += (vbi->vbi_size / 2);
-		memcpy(buf + vbi->copied, src, count);
-	}
-	vbi->copied += count;
-}
-
-/*
- * Copy the normal data (VBI or VIDEO) without the trailer.
- * VBI is not interlaced, while VIDEO is interlaced.
- */
-static inline void copy_vbi_video_data(struct video_data *video,
-				char *src, unsigned int count)
-{
-	struct vbi_data *vbi = video->vbi;
-	unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied;
-
-	if (vbi_delta >= count) {
-		copy_vbi_data(vbi, src, count);
-	} else {
-		if (vbi_delta) {
-			copy_vbi_data(vbi, src, vbi_delta);
-
-			/* we receive the two fields of the VBI*/
-			if (vbi->front && video->field_count)
-				submit_frame(vbi->front);
-		}
-		copy_video_data(video, src + vbi_delta, count - vbi_delta);
-	}
-}
-
-static void urb_complete_bulk(struct urb *urb)
-{
-	struct front_face *front = urb->context;
-	struct video_data *video = &front->pd->video_data;
-	char *src = (char *)urb->transfer_buffer;
-	int count = urb->actual_length;
-	int ret = 0;
-
-	if (!video->is_streaming || urb->status) {
-		if (urb->status == -EPROTO)
-			goto resend_it;
-		return;
-	}
-	if (!get_video_frame(front, video))
-		goto resend_it;
-
-	if (count == urb->transfer_buffer_length)
-		copy_vbi_video_data(video, src, count);
-	else
-		check_trailer(video, src, count);
-
-resend_it:
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret)
-		log(" submit failed: error %d", ret);
-}
-
-/************************* for ISO *********************/
-#define GET_SUCCESS		(0)
-#define GET_TRAILER		(1)
-#define GET_TOO_MUCH_BUBBLE	(2)
-#define GET_NONE		(3)
-static int get_chunk(int start, struct urb *urb,
-			int *head, int *tail, int *bubble_err)
-{
-	struct usb_iso_packet_descriptor *pkt = NULL;
-	int ret = GET_SUCCESS;
-
-	for (*head = *tail = -1; start < urb->number_of_packets; start++) {
-		pkt = &urb->iso_frame_desc[start];
-
-		/* handle the bubble of the Hub */
-		if (-EOVERFLOW == pkt->status) {
-			if (++*bubble_err > urb->number_of_packets / 3)
-				return GET_TOO_MUCH_BUBBLE;
-			continue;
-		}
-
-		/* This is the gap */
-		if (pkt->status || pkt->actual_length <= 0
-				|| pkt->actual_length > ISO_PKT_SIZE) {
-			if (*head != -1)
-				break;
-			continue;
-		}
-
-		/* a good isochronous packet */
-		if (pkt->actual_length == ISO_PKT_SIZE) {
-			if (*head == -1)
-				*head = start;
-			*tail = start;
-			continue;
-		}
-
-		/* trailer is here */
-		if (pkt->actual_length < ISO_PKT_SIZE) {
-			if (*head == -1) {
-				*head = start;
-				*tail = start;
-				return GET_TRAILER;
-			}
-			break;
-		}
-	}
-
-	if (*head == -1 && *tail == -1)
-		ret = GET_NONE;
-	return ret;
-}
-
-/*
- * |__|------|___|-----|_______|
- *       ^          ^
- *       |          |
- *      gap        gap
- */
-static void urb_complete_iso(struct urb *urb)
-{
-	struct front_face *front = urb->context;
-	struct video_data *video = &front->pd->video_data;
-	int bubble_err = 0, head = 0, tail = 0;
-	char *src = (char *)urb->transfer_buffer;
-	int ret = 0;
-
-	if (!video->is_streaming)
-		return;
-
-	do {
-		if (!get_video_frame(front, video))
-			goto out;
-
-		switch (get_chunk(head, urb, &head, &tail, &bubble_err)) {
-		case GET_SUCCESS:
-			copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE),
-					(tail - head + 1) * ISO_PKT_SIZE);
-			break;
-		case GET_TRAILER:
-			check_trailer(video, src + (head * ISO_PKT_SIZE),
-					ISO_PKT_SIZE);
-			break;
-		case GET_NONE:
-			goto out;
-		case GET_TOO_MUCH_BUBBLE:
-			log("\t We got too much bubble");
-			schedule_work(&video->bubble_work);
-			return;
-		}
-	} while (head = tail + 1, head < urb->number_of_packets);
-
-out:
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret)
-		log("usb_submit_urb err : %d", ret);
-}
-/*============================= [  end  ] =====================*/
-
-static int prepare_iso_urb(struct video_data *video)
-{
-	struct usb_device *udev = video->pd->udev;
-	int i;
-
-	if (video->urb_array[0])
-		return 0;
-
-	for (i = 0; i < SBUF_NUM; i++) {
-		struct urb *urb;
-		void *mem;
-		int j;
-
-		urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL);
-		if (urb == NULL)
-			goto out;
-
-		video->urb_array[i] = urb;
-		mem = usb_alloc_coherent(udev,
-					 ISO_PKT_SIZE * PK_PER_URB,
-					 GFP_KERNEL,
-					 &urb->transfer_dma);
-
-		urb->complete	= urb_complete_iso;	/* handler */
-		urb->dev	= udev;
-		urb->context	= video->front;
-		urb->pipe	= usb_rcvisocpipe(udev,
-						video->endpoint_addr);
-		urb->interval	= 1;
-		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-		urb->number_of_packets	= PK_PER_URB;
-		urb->transfer_buffer	= mem;
-		urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE;
-
-		for (j = 0; j < PK_PER_URB; j++) {
-			urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j;
-			urb->iso_frame_desc[j].length = ISO_PKT_SIZE;
-		}
-	}
-	return 0;
-out:
-	for (; i > 0; i--)
-		;
-	return -ENOMEM;
-}
-
-/* return the succeeded number of the allocation */
-int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
-			struct usb_device *udev, u8 ep_addr,
-			int buf_size, gfp_t gfp_flags,
-			usb_complete_t complete_fn, void *context)
-{
-	int i = 0;
-
-	for (; i < num; i++) {
-		void *mem;
-		struct urb *urb = usb_alloc_urb(0, gfp_flags);
-		if (urb == NULL)
-			return i;
-
-		mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
-					 &urb->transfer_dma);
-		if (mem == NULL) {
-			usb_free_urb(urb);
-			return i;
-		}
-
-		usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr),
-				mem, buf_size, complete_fn, context);
-		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-		urb_array[i] = urb;
-	}
-	return i;
-}
-
-void free_all_urb_generic(struct urb **urb_array, int num)
-{
-	int i;
-	struct urb *urb;
-
-	for (i = 0; i < num; i++) {
-		urb = urb_array[i];
-		if (urb) {
-			usb_free_coherent(urb->dev,
-					urb->transfer_buffer_length,
-					urb->transfer_buffer,
-					urb->transfer_dma);
-			usb_free_urb(urb);
-			urb_array[i] = NULL;
-		}
-	}
-}
-
-static int prepare_bulk_urb(struct video_data *video)
-{
-	if (video->urb_array[0])
-		return 0;
-
-	alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM,
-			video->pd->udev, video->endpoint_addr,
-			0x2000, GFP_KERNEL,
-			urb_complete_bulk, video->front);
-	return 0;
-}
-
-/* free the URBs */
-static void free_all_urb(struct video_data *video)
-{
-	free_all_urb_generic(video->urb_array, SBUF_NUM);
-}
-
-static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-	videobuf_vmalloc_free(vb);
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-	struct front_face *front = q->priv_data;
-	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &front->active);
-}
-
-static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-			   enum v4l2_field field)
-{
-	struct front_face *front = q->priv_data;
-	int rc;
-
-	switch (front->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		if (VIDEOBUF_NEEDS_INIT == vb->state) {
-			struct v4l2_pix_format *pix;
-
-			pix = &front->pd->video_data.context.pix;
-			vb->size	= pix->sizeimage; /* real frame size */
-			vb->width	= pix->width;
-			vb->height	= pix->height;
-			rc = videobuf_iolock(q, vb, NULL);
-			if (rc < 0)
-				return rc;
-		}
-		break;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		if (VIDEOBUF_NEEDS_INIT == vb->state) {
-			vb->size	= front->pd->vbi_data.vbi_size;
-			rc = videobuf_iolock(q, vb, NULL);
-			if (rc < 0)
-				return rc;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-	vb->field = field;
-	vb->state = VIDEOBUF_PREPARED;
-	return 0;
-}
-
-static int fire_all_urb(struct video_data *video)
-{
-	int i, ret;
-
-	video->is_streaming = 1;
-
-	for (i = 0; i < SBUF_NUM; i++) {
-		ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL);
-		if (ret)
-			log("(%d) failed: error %d", i, ret);
-	}
-	return ret;
-}
-
-static int start_video_stream(struct poseidon *pd)
-{
-	struct video_data *video = &pd->video_data;
-	s32 cmd_status;
-
-	send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
-	send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status);
-
-	if (pd->cur_transfer_mode) {
-		prepare_iso_urb(video);
-		INIT_WORK(&video->bubble_work, iso_bubble_handler);
-	} else {
-		/* The bulk mode does not need a bubble handler */
-		prepare_bulk_urb(video);
-	}
-	fire_all_urb(video);
-	return 0;
-}
-
-static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count,
-		       unsigned int *size)
-{
-	struct front_face *front = q->priv_data;
-	struct poseidon *pd	= front->pd;
-
-	switch (front->type) {
-	default:
-		return -EINVAL;
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct video_data *video = &pd->video_data;
-		struct v4l2_pix_format *pix = &video->context.pix;
-
-		*size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */
-		if (*count < 4)
-			*count = 4;
-		if (1) {
-			/* same in different altersetting */
-			video->endpoint_addr	= 0x82;
-			video->vbi		= &pd->vbi_data;
-			video->vbi->video	= video;
-			video->pd		= pd;
-			video->lines_per_field	= pix->height / 2;
-			video->lines_size	= pix->width * 2;
-			video->front 		= front;
-		}
-		return start_video_stream(pd);
-	}
-
-	case V4L2_BUF_TYPE_VBI_CAPTURE: {
-		struct vbi_data *vbi = &pd->vbi_data;
-
-		*size = PAGE_ALIGN(vbi->vbi_size);
-		log("size : %d", *size);
-		if (*count == 0)
-			*count = 4;
-	}
-		break;
-	}
-	return 0;
-}
-
-static struct videobuf_queue_ops pd_video_qops = {
-	.buf_setup      = pd_buf_setup,
-	.buf_prepare    = pd_buf_prepare,
-	.buf_queue      = pd_buf_queue,
-	.buf_release    = pd_buf_release,
-};
-
-static int vidioc_enum_fmt(struct file *file, void *fh,
-				struct v4l2_fmtdesc *f)
-{
-	if (ARRAY_SIZE(poseidon_formats) <= f->index)
-		return -EINVAL;
-	f->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	f->flags	= 0;
-	f->pixelformat	= poseidon_formats[f->index].fourcc;
-	strcpy(f->description, poseidon_formats[f->index].name);
-	return 0;
-}
-
-static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
-{
-	struct front_face *front = fh;
-	struct poseidon *pd = front->pd;
-
-	f->fmt.pix = pd->video_data.context.pix;
-	return 0;
-}
-
-/*
- * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while
- * Mplayer calls them in the reverse order.
- */
-static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix)
-{
-	struct video_data *video	= &pd->video_data;
-	struct running_context *context = &video->context;
-	struct v4l2_pix_format *pix_def	= &context->pix;
-	s32 ret = 0, cmd_status = 0, vid_resol;
-
-	/* set the pixel format to firmware */
-	if (pix->pixelformat == V4L2_PIX_FMT_RGB565) {
-		vid_resol = TLG_TUNER_VID_FORMAT_RGB_565;
-	} else {
-		pix->pixelformat = V4L2_PIX_FMT_YUYV;
-		vid_resol = TLG_TUNER_VID_FORMAT_YUV;
-	}
-	ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL,
-				vid_resol, &cmd_status);
-
-	/* set the resolution to firmware */
-	vid_resol = TLG_TUNE_VID_RES_720;
-	switch (pix->width) {
-	case 704:
-		vid_resol = TLG_TUNE_VID_RES_704;
-		break;
-	default:
-		pix->width = 720;
-	case 720:
-		break;
-	}
-	ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
-				vid_resol, &cmd_status);
-	if (ret || cmd_status)
-		return -EBUSY;
-
-	pix_def->pixelformat = pix->pixelformat; /* save it */
-	pix->height = (context->tvnormid & V4L2_STD_525_60) ?  480 : 576;
-
-	/* Compare with the default setting */
-	if ((pix_def->width != pix->width)
-		|| (pix_def->height != pix->height)) {
-		pix_def->width		= pix->width;
-		pix_def->height		= pix->height;
-		pix_def->bytesperline	= pix->width * 2;
-		pix_def->sizeimage 	= pix->width * pix->height * 2;
-	}
-	*pix = *pix_def;
-
-	return 0;
-}
-
-static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
-{
-	struct front_face *front	= fh;
-	struct poseidon *pd		= front->pd;
-
-	/* stop VBI here */
-	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
-		return -EINVAL;
-
-	mutex_lock(&pd->lock);
-	if (pd->file_for_stream == NULL)
-		pd->file_for_stream = file;
-	else if (file != pd->file_for_stream) {
-		mutex_unlock(&pd->lock);
-		return -EINVAL;
-	}
-
-	pd_vidioc_s_fmt(pd, &f->fmt.pix);
-	mutex_unlock(&pd->lock);
-	return 0;
-}
-
-static int vidioc_g_fmt_vbi(struct file *file, void *fh,
-			       struct v4l2_format *v4l2_f)
-{
-	struct front_face *front	= fh;
-	struct poseidon *pd		= front->pd;
-	struct v4l2_vbi_format *vbi_fmt	= &v4l2_f->fmt.vbi;
-
-	vbi_fmt->samples_per_line	= 720 * 2;
-	vbi_fmt->sampling_rate		= 6750000 * 4;
-	vbi_fmt->sample_format		= V4L2_PIX_FMT_GREY;
-	vbi_fmt->offset			= 64 * 4;  /*FIXME: why offset */
-	if (pd->video_data.context.tvnormid & V4L2_STD_525_60) {
-		vbi_fmt->start[0] = 10;
-		vbi_fmt->start[1] = 264;
-		vbi_fmt->count[0] = V4L_NTSC_VBI_LINES;
-		vbi_fmt->count[1] = V4L_NTSC_VBI_LINES;
-	} else {
-		vbi_fmt->start[0] = 6;
-		vbi_fmt->start[1] = 314;
-		vbi_fmt->count[0] = V4L_PAL_VBI_LINES;
-		vbi_fmt->count[1] = V4L_PAL_VBI_LINES;
-	}
-	vbi_fmt->flags = V4L2_VBI_UNSYNC;
-	return 0;
-}
-
-static int set_std(struct poseidon *pd, v4l2_std_id norm)
-{
-	struct video_data *video = &pd->video_data;
-	struct vbi_data *vbi	= &pd->vbi_data;
-	struct running_context *context;
-	struct v4l2_pix_format *pix;
-	s32 i, ret = 0, cmd_status, param;
-	int height;
-
-	for (i = 0; i < POSEIDON_TVNORMS; i++) {
-		if (norm & poseidon_tvnorms[i].v4l2_id) {
-			param = poseidon_tvnorms[i].tlg_tvnorm;
-			log("name : %s", poseidon_tvnorms[i].name);
-			goto found;
-		}
-	}
-	return -EINVAL;
-found:
-	mutex_lock(&pd->lock);
-	ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status);
-	if (ret || cmd_status)
-		goto out;
-
-	/* Set vbi size and check the height of the frame */
-	context = &video->context;
-	context->tvnormid = poseidon_tvnorms[i].v4l2_id;
-	if (context->tvnormid & V4L2_STD_525_60) {
-		vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE;
-		height = 480;
-	} else {
-		vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE;
-		height = 576;
-	}
-
-	pix = &context->pix;
-	if (pix->height != height) {
-		pix->height	= height;
-		pix->sizeimage 	= pix->width * pix->height * 2;
-	}
-
-out:
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id norm)
-{
-	struct front_face *front = fh;
-
-	return set_std(front->pd, norm);
-}
-
-static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
-	struct front_face *front = fh;
-
-	*norm = front->pd->video_data.context.tvnormid;
-	return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
-{
-	if (in->index >= POSEIDON_INPUTS)
-		return -EINVAL;
-	strcpy(in->name, pd_inputs[in->index].name);
-	in->type  = V4L2_INPUT_TYPE_TUNER;
-
-	/*
-	 * the audio input index mixed with this video input,
-	 * Poseidon only have one audio/video, set to "0"
-	 */
-	in->audioset	= 1;
-	in->tuner	= 0;
-	in->std		= V4L2_STD_ALL;
-	in->status	= 0;
-	return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
-{
-	struct front_face *front = fh;
-	struct poseidon *pd = front->pd;
-	struct running_context *context = &pd->video_data.context;
-
-	*i = context->sig_index;
-	return 0;
-}
-
-/* We can support several inputs */
-static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
-{
-	struct front_face *front = fh;
-	struct poseidon *pd = front->pd;
-	s32 ret, cmd_status;
-
-	if (i >= POSEIDON_INPUTS)
-		return -EINVAL;
-	ret = send_set_req(pd, SGNL_SRC_SEL,
-			pd_inputs[i].tlg_src, &cmd_status);
-	if (ret)
-		return ret;
-
-	pd->video_data.context.sig_index = i;
-	return 0;
-}
-
-static int tlg_s_ctrl(struct v4l2_ctrl *c)
-{
-	struct poseidon *pd = container_of(c->handler, struct poseidon,
-						video_data.ctrl_handler);
-	struct tuner_custom_parameter_s param = {0};
-	s32 ret = 0, cmd_status, params;
-
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		param.param_id = CUST_PARM_ID_BRIGHTNESS_CTRL;
-		break;
-	case V4L2_CID_CONTRAST:
-		param.param_id = CUST_PARM_ID_CONTRAST_CTRL;
-		break;
-	case V4L2_CID_HUE:
-		param.param_id = CUST_PARM_ID_HUE_CTRL;
-		break;
-	case V4L2_CID_SATURATION:
-		param.param_id = CUST_PARM_ID_SATURATION_CTRL;
-		break;
-	}
-	param.param_value = c->val;
-	params = *(s32 *)&param; /* temp code */
-
-	mutex_lock(&pd->lock);
-	ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status);
-	ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
-	mutex_unlock(&pd->lock);
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/4);
-	return ret;
-}
-
-/* Audio ioctls */
-static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-	if (0 != a->index)
-		return -EINVAL;
-	a->capability = V4L2_AUDCAP_STEREO;
-	strcpy(a->name, "USB audio in");
-	/*Poseidon have no AVL function.*/
-	a->mode = 0;
-	return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-	a->index = 0;
-	a->capability = V4L2_AUDCAP_STEREO;
-	strcpy(a->name, "USB audio in");
-	a->mode = 0;
-	return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
-{
-	return (0 == a->index) ? 0 : -EINVAL;
-}
-
-/* Tuner ioctls */
-static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner)
-{
-	struct front_face *front	= fh;
-	struct poseidon *pd		= front->pd;
-	struct tuner_atv_sig_stat_s atv_stat;
-	s32 count = 5, ret, cmd_status;
-	int index;
-
-	if (0 != tuner->index)
-		return -EINVAL;
-
-	mutex_lock(&pd->lock);
-	ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
-				&atv_stat, &cmd_status, sizeof(atv_stat));
-
-	while (atv_stat.sig_lock_busy && count-- && !ret) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ);
-
-		ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
-				&atv_stat, &cmd_status, sizeof(atv_stat));
-	}
-	mutex_unlock(&pd->lock);
-
-	if (debug_mode)
-		log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength);
-
-	if (ret || cmd_status)
-		tuner->signal = 0;
-	else if (atv_stat.sig_present && !atv_stat.sig_strength)
-		tuner->signal = 0xFFFF;
-	else
-		tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8;
-
-	strcpy(tuner->name, "Telegent Systems");
-	tuner->type = V4L2_TUNER_ANALOG_TV;
-	tuner->rangelow = TUNER_FREQ_MIN / 62500;
-	tuner->rangehigh = TUNER_FREQ_MAX / 62500;
-	tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
-				V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
-	index = pd->video_data.context.audio_idx;
-	tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub;
-	tuner->audmode = pd_audio_modes[index].v4l2_audio_mode;
-	tuner->afc = 0;
-	return 0;
-}
-
-static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
-{
-	s32 ret = 0, cmd_status, param, audiomode;
-
-	mutex_lock(&pd->lock);
-	param = pd_audio_modes[index].tlg_audio_mode;
-	ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status);
-	audiomode = get_audio_std(pd->video_data.context.tvnormid);
-	ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode,
-				&cmd_status);
-	if (!ret)
-		pd->video_data.context.audio_idx = index;
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *a)
-{
-	struct front_face *front	= fh;
-	struct poseidon *pd		= front->pd;
-	int index;
-
-	if (0 != a->index)
-		return -EINVAL;
-	for (index = 0; index < POSEIDON_AUDIOMODS; index++)
-		if (a->audmode == pd_audio_modes[index].v4l2_audio_mode)
-			return pd_vidioc_s_tuner(pd, index);
-	return -EINVAL;
-}
-
-static int vidioc_g_frequency(struct file *file, void *fh,
-			struct v4l2_frequency *freq)
-{
-	struct front_face *front = fh;
-	struct poseidon *pd = front->pd;
-	struct running_context *context = &pd->video_data.context;
-
-	if (0 != freq->tuner)
-		return -EINVAL;
-	freq->frequency = context->freq;
-	freq->type = V4L2_TUNER_ANALOG_TV;
-	return 0;
-}
-
-static int set_frequency(struct poseidon *pd, u32 *frequency)
-{
-	s32 ret = 0, param, cmd_status;
-	struct running_context *context = &pd->video_data.context;
-
-	*frequency = clamp(*frequency,
-			TUNER_FREQ_MIN / 62500, TUNER_FREQ_MAX / 62500);
-	param = (*frequency) * 62500 / 1000;
-
-	mutex_lock(&pd->lock);
-	ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status);
-	ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
-
-	msleep(250); /* wait for a while until the hardware is ready. */
-	context->freq = *frequency;
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static int vidioc_s_frequency(struct file *file, void *fh,
-				const struct v4l2_frequency *freq)
-{
-	struct front_face *front = fh;
-	struct poseidon *pd = front->pd;
-	u32 frequency = freq->frequency;
-
-	if (freq->tuner)
-		return -EINVAL;
-#ifdef CONFIG_PM
-	pd->pm_suspend = pm_video_suspend;
-	pd->pm_resume = pm_video_resume;
-#endif
-	return set_frequency(pd, &frequency);
-}
-
-static int vidioc_reqbufs(struct file *file, void *fh,
-				struct v4l2_requestbuffers *b)
-{
-	struct front_face *front = file->private_data;
-	return videobuf_reqbufs(&front->q, b);
-}
-
-static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
-{
-	struct front_face *front = file->private_data;
-	return videobuf_querybuf(&front->q, b);
-}
-
-static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
-{
-	struct front_face *front = file->private_data;
-	return videobuf_qbuf(&front->q, b);
-}
-
-static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
-{
-	struct front_face *front = file->private_data;
-	return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK);
-}
-
-/* Just stop the URBs, do not free the URBs */
-static int usb_transfer_stop(struct video_data *video)
-{
-	if (video->is_streaming) {
-		int i;
-		s32 cmd_status;
-		struct poseidon *pd = video->pd;
-
-		video->is_streaming = 0;
-		for (i = 0; i < SBUF_NUM; ++i) {
-			if (video->urb_array[i])
-				usb_kill_urb(video->urb_array[i]);
-		}
-
-		send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
-			       &cmd_status);
-	}
-	return 0;
-}
-
-int stop_all_video_stream(struct poseidon *pd)
-{
-	struct video_data *video = &pd->video_data;
-	struct vbi_data *vbi	= &pd->vbi_data;
-
-	mutex_lock(&pd->lock);
-	if (video->is_streaming) {
-		struct front_face *front = video->front;
-
-		/* stop the URBs */
-		usb_transfer_stop(video);
-		free_all_urb(video);
-
-		/* stop the host side of VIDEO */
-		videobuf_stop(&front->q);
-		videobuf_mmap_free(&front->q);
-
-		/* stop the host side of VBI */
-		front = vbi->front;
-		if (front) {
-			videobuf_stop(&front->q);
-			videobuf_mmap_free(&front->q);
-		}
-	}
-	mutex_unlock(&pd->lock);
-	return 0;
-}
-
-/*
- * The bubbles can seriously damage the video's quality,
- * though it occurs in very rare situation.
- */
-static void iso_bubble_handler(struct work_struct *w)
-{
-	struct video_data *video;
-	struct poseidon *pd;
-
-	video = container_of(w, struct video_data, bubble_work);
-	pd = video->pd;
-
-	mutex_lock(&pd->lock);
-	usb_transfer_stop(video);
-	msleep(500);
-	start_video_stream(pd);
-	mutex_unlock(&pd->lock);
-}
-
-
-static int vidioc_streamon(struct file *file, void *fh,
-				enum v4l2_buf_type type)
-{
-	struct front_face *front = fh;
-
-	if (unlikely(type != front->type))
-		return -EINVAL;
-	return videobuf_streamon(&front->q);
-}
-
-static int vidioc_streamoff(struct file *file, void *fh,
-				enum v4l2_buf_type type)
-{
-	struct front_face *front = file->private_data;
-
-	if (unlikely(type != front->type))
-		return -EINVAL;
-	return videobuf_streamoff(&front->q);
-}
-
-/* Set the firmware's default values : need altersetting */
-static int pd_video_checkmode(struct poseidon *pd)
-{
-	s32 ret = 0, cmd_status, audiomode;
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/2);
-
-	/* choose the altersetting */
-	ret = usb_set_interface(pd->udev, 0,
-					(pd->cur_transfer_mode ?
-					 ISO_3K_BULK_ALTERNATE_IFACE :
-					 BULK_ALTERNATE_IFACE));
-	if (ret < 0)
-		goto error;
-
-	/* set default parameters for PAL-D , with the VBI enabled*/
-	ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV);
-	ret |= send_set_req(pd, SGNL_SRC_SEL,
-				TLG_SIG_SRC_ANTENNA, &cmd_status);
-	ret |= send_set_req(pd, VIDEO_STD_SEL,
-				TLG_TUNE_VSTD_PAL_D, &cmd_status);
-	ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL,
-				TLG_TUNER_VID_FORMAT_YUV, &cmd_status);
-	ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
-				TLG_TUNE_VID_RES_720, &cmd_status);
-	ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status);
-	ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
-
-	/* set the audio */
-	audiomode = get_audio_std(pd->video_data.context.tvnormid);
-	ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status);
-	ret |= send_set_req(pd, TUNER_AUD_MODE,
-				TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
-	ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL,
-				ATV_AUDIO_RATE_48K, &cmd_status);
-error:
-	return ret;
-}
-
-#ifdef CONFIG_PM
-static int pm_video_suspend(struct poseidon *pd)
-{
-	/* stop audio */
-	pm_alsa_suspend(pd);
-
-	/* stop and free all the URBs */
-	usb_transfer_stop(&pd->video_data);
-	free_all_urb(&pd->video_data);
-
-	/* reset the interface */
-	usb_set_interface(pd->udev, 0, 0);
-	msleep(300);
-	return 0;
-}
-
-static int restore_v4l2_context(struct poseidon *pd,
-				struct running_context *context)
-{
-	struct front_face *front = pd->video_data.front;
-
-	pd_video_checkmode(pd);
-
-	set_std(pd, context->tvnormid);
-	vidioc_s_input(NULL, front, context->sig_index);
-	pd_vidioc_s_tuner(pd, context->audio_idx);
-	pd_vidioc_s_fmt(pd, &context->pix);
-	set_frequency(pd, &context->freq);
-	return 0;
-}
-
-static int pm_video_resume(struct poseidon *pd)
-{
-	struct video_data *video = &pd->video_data;
-
-	/* resume the video */
-	/* [1] restore the origin V4L2 parameters */
-	restore_v4l2_context(pd, &video->context);
-
-	/* [2] initiate video copy variables */
-	if (video->front->curr_frame)
-		init_copy(video, 0);
-
-	/* [3] fire urbs	*/
-	start_video_stream(pd);
-
-	/* resume the audio */
-	pm_alsa_resume(pd);
-	return 0;
-}
-#endif
-
-void set_debug_mode(struct video_device *vfd, int debug_mode)
-{
-	vfd->debug = 0;
-	if (debug_mode & 0x1)
-		vfd->debug = V4L2_DEBUG_IOCTL;
-	if (debug_mode & 0x2)
-		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
-}
-
-static void init_video_context(struct running_context *context)
-{
-	context->sig_index	= 0;
-	context->audio_idx	= 1; /* stereo */
-	context->tvnormid  	= V4L2_STD_PAL_D;
-	context->pix = (struct v4l2_pix_format) {
-				.width		= 720,
-				.height		= 576,
-				.pixelformat	= V4L2_PIX_FMT_YUYV,
-				.field		= V4L2_FIELD_INTERLACED,
-				.bytesperline	= 720 * 2,
-				.sizeimage	= 720 * 576 * 2,
-				.colorspace	= V4L2_COLORSPACE_SMPTE170M,
-			};
-}
-
-static int pd_video_open(struct file *file)
-{
-	struct video_device *vfd = video_devdata(file);
-	struct poseidon *pd = video_get_drvdata(vfd);
-	struct front_face *front = NULL;
-	int ret = -ENOMEM;
-
-	mutex_lock(&pd->lock);
-	usb_autopm_get_interface(pd->interface);
-
-	if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) {
-		ret = -EBUSY;
-		goto out;
-	}
-	front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-	if (!front)
-		goto out;
-	if (vfd->vfl_type == VFL_TYPE_GRABBER) {
-		pd->cur_transfer_mode	= usb_transfer_mode;/* bulk or iso */
-		init_video_context(&pd->video_data.context);
-
-		ret = pd_video_checkmode(pd);
-		if (ret < 0) {
-			kfree(front);
-			ret = -1;
-			goto out;
-		}
-
-		front->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		pd->video_data.users++;
-		set_debug_mode(vfd, debug_mode);
-
-		videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
-				NULL, &front->queue_lock,
-				V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				V4L2_FIELD_INTERLACED,/* video is interlacd */
-				sizeof(struct videobuf_buffer),/*it's enough*/
-				front, NULL);
-	} else {
-		front->type	= V4L2_BUF_TYPE_VBI_CAPTURE;
-		pd->vbi_data.front = front;
-		pd->vbi_data.users++;
-
-		videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
-				NULL, &front->queue_lock,
-				V4L2_BUF_TYPE_VBI_CAPTURE,
-				V4L2_FIELD_NONE, /* vbi is NONE mode */
-				sizeof(struct videobuf_buffer),
-				front, NULL);
-	}
-
-	pd->state |= POSEIDON_STATE_ANALOG;
-	front->pd = pd;
-	front->curr_frame = NULL;
-	INIT_LIST_HEAD(&front->active);
-	spin_lock_init(&front->queue_lock);
-
-	file->private_data = front;
-	kref_get(&pd->kref);
-
-	mutex_unlock(&pd->lock);
-	return 0;
-out:
-	usb_autopm_put_interface(pd->interface);
-	mutex_unlock(&pd->lock);
-	return ret;
-}
-
-static int pd_video_release(struct file *file)
-{
-	struct front_face *front = file->private_data;
-	struct poseidon *pd = front->pd;
-	s32 cmd_status = 0;
-
-	mutex_lock(&pd->lock);
-
-	if (front->type	== V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		/* stop the device, and free the URBs */
-		usb_transfer_stop(&pd->video_data);
-		free_all_urb(&pd->video_data);
-
-		/* stop the firmware */
-		send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
-			       &cmd_status);
-
-		pd->file_for_stream = NULL;
-		pd->video_data.users--;
-	} else if (front->type	== V4L2_BUF_TYPE_VBI_CAPTURE) {
-		pd->vbi_data.front = NULL;
-		pd->vbi_data.users--;
-	}
-	if (!pd->vbi_data.users && !pd->video_data.users)
-		pd->state &= ~POSEIDON_STATE_ANALOG;
-	videobuf_stop(&front->q);
-	videobuf_mmap_free(&front->q);
-
-	usb_autopm_put_interface(pd->interface);
-	mutex_unlock(&pd->lock);
-
-	kfree(front);
-	file->private_data = NULL;
-	kref_put(&pd->kref, poseidon_delete);
-	return 0;
-}
-
-static int pd_video_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct front_face *front = file->private_data;
-	return  videobuf_mmap_mapper(&front->q, vma);
-}
-
-static unsigned int pd_video_poll(struct file *file, poll_table *table)
-{
-	struct front_face *front = file->private_data;
-	return videobuf_poll_stream(file, &front->q, table);
-}
-
-static ssize_t pd_video_read(struct file *file, char __user *buffer,
-			size_t count, loff_t *ppos)
-{
-	struct front_face *front = file->private_data;
-	return videobuf_read_stream(&front->q, buffer, count, ppos,
-				0, file->f_flags & O_NONBLOCK);
-}
-
-/* This struct works for both VIDEO and VBI */
-static const struct v4l2_file_operations pd_video_fops = {
-	.owner		= THIS_MODULE,
-	.open		= pd_video_open,
-	.release	= pd_video_release,
-	.read		= pd_video_read,
-	.poll		= pd_video_poll,
-	.mmap		= pd_video_mmap,
-	.ioctl		= video_ioctl2, /* maybe changed in future */
-};
-
-static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
-	.vidioc_querycap	= vidioc_querycap,
-
-	/* Video format */
-	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt,
-	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt,
-	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt,
-	.vidioc_g_fmt_vbi_cap	= vidioc_g_fmt_vbi, /* VBI */
-
-	/* Input */
-	.vidioc_g_input		= vidioc_g_input,
-	.vidioc_s_input		= vidioc_s_input,
-	.vidioc_enum_input	= vidioc_enum_input,
-
-	/* Audio ioctls */
-	.vidioc_enumaudio	= vidioc_enumaudio,
-	.vidioc_g_audio		= vidioc_g_audio,
-	.vidioc_s_audio		= vidioc_s_audio,
-
-	/* Tuner ioctls */
-	.vidioc_g_tuner		= vidioc_g_tuner,
-	.vidioc_s_tuner		= vidioc_s_tuner,
-	.vidioc_g_std		= vidioc_g_std,
-	.vidioc_s_std		= vidioc_s_std,
-	.vidioc_g_frequency	= vidioc_g_frequency,
-	.vidioc_s_frequency	= vidioc_s_frequency,
-
-	/* Buffer handlers */
-	.vidioc_reqbufs		= vidioc_reqbufs,
-	.vidioc_querybuf	= vidioc_querybuf,
-	.vidioc_qbuf		= vidioc_qbuf,
-	.vidioc_dqbuf		= vidioc_dqbuf,
-
-	/* Stream on/off */
-	.vidioc_streamon	= vidioc_streamon,
-	.vidioc_streamoff	= vidioc_streamoff,
-};
-
-static struct video_device pd_video_template = {
-	.name = "Telegent-Video",
-	.fops = &pd_video_fops,
-	.minor = -1,
-	.release = video_device_release_empty,
-	.tvnorms = V4L2_STD_ALL,
-	.ioctl_ops = &pd_video_ioctl_ops,
-};
-
-static const struct v4l2_ctrl_ops tlg_ctrl_ops = {
-	.s_ctrl = tlg_s_ctrl,
-};
-
-void pd_video_exit(struct poseidon *pd)
-{
-	struct video_data *video = &pd->video_data;
-	struct vbi_data *vbi = &pd->vbi_data;
-
-	video_unregister_device(&video->v_dev);
-	video_unregister_device(&vbi->v_dev);
-	v4l2_ctrl_handler_free(&video->ctrl_handler);
-	log();
-}
-
-int pd_video_init(struct poseidon *pd)
-{
-	struct video_data *video = &pd->video_data;
-	struct vbi_data *vbi	= &pd->vbi_data;
-	struct v4l2_ctrl_handler *hdl = &video->ctrl_handler;
-	u32 freq = TUNER_FREQ_MIN / 62500;
-	int ret = -ENOMEM;
-
-	v4l2_ctrl_handler_init(hdl, 4);
-	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_BRIGHTNESS,
-			0, 10000, 1, 100);
-	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_CONTRAST,
-			0, 10000, 1, 100);
-	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_HUE,
-			0, 10000, 1, 100);
-	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_SATURATION,
-			0, 10000, 1, 100);
-	if (hdl->error) {
-		v4l2_ctrl_handler_free(hdl);
-		return hdl->error;
-	}
-	set_frequency(pd, &freq);
-	video->v_dev = pd_video_template;
-	video->v_dev.v4l2_dev = &pd->v4l2_dev;
-	video->v_dev.ctrl_handler = hdl;
-	video_set_drvdata(&video->v_dev, pd);
-
-	ret = video_register_device(&video->v_dev, VFL_TYPE_GRABBER, -1);
-	if (ret != 0)
-		goto out;
-
-	/* VBI uses the same template as video */
-	vbi->v_dev = pd_video_template;
-	vbi->v_dev.v4l2_dev = &pd->v4l2_dev;
-	vbi->v_dev.ctrl_handler = hdl;
-	video_set_drvdata(&vbi->v_dev, pd);
-	ret = video_register_device(&vbi->v_dev, VFL_TYPE_VBI, -1);
-	if (ret != 0)
-		goto out;
-	log("register VIDEO/VBI devices");
-	return 0;
-out:
-	log("VIDEO/VBI devices register failed, : %d", ret);
-	pd_video_exit(pd);
-	return ret;
-}
diff --git a/drivers/staging/media/tlg2300/vendorcmds.h b/drivers/staging/media/tlg2300/vendorcmds.h
deleted file mode 100644
index ba6f4ae3b2c2..000000000000
--- a/drivers/staging/media/tlg2300/vendorcmds.h
+++ /dev/null
@@ -1,243 +0,0 @@
-#ifndef VENDOR_CMD_H_
-#define VENDOR_CMD_H_
-
-#define BULK_ALTERNATE_IFACE		(2)
-#define ISO_3K_BULK_ALTERNATE_IFACE     (1)
-#define REQ_SET_CMD			(0X00)
-#define REQ_GET_CMD			(0X80)
-
-enum tlg__analog_audio_standard {
-	TLG_TUNE_ASTD_NONE	= 0x00000000,
-	TLG_TUNE_ASTD_A2	= 0x00000001,
-	TLG_TUNE_ASTD_NICAM	= 0x00000002,
-	TLG_TUNE_ASTD_EIAJ	= 0x00000004,
-	TLG_TUNE_ASTD_BTSC	= 0x00000008,
-	TLG_TUNE_ASTD_FM_US	= 0x00000010,
-	TLG_TUNE_ASTD_FM_EUR	= 0x00000020,
-	TLG_TUNE_ASTD_ALL	= 0x0000003f
-};
-
-/*
- * identifiers for Custom Parameter messages.
- * @typedef cmd_custom_param_id_t
- */
-enum cmd_custom_param_id {
-	CUST_PARM_ID_NONE		= 0x00,
-	CUST_PARM_ID_BRIGHTNESS_CTRL	= 0x01,
-	CUST_PARM_ID_CONTRAST_CTRL	= 0x02,
-	CUST_PARM_ID_HUE_CTRL		= 0x03,
-	CUST_PARM_ID_SATURATION_CTRL	  = 0x04,
-	CUST_PARM_ID_AUDIO_SNR_THRESHOLD  = 0x10,
-	CUST_PARM_ID_AUDIO_AGC_THRESHOLD  = 0x11,
-	CUST_PARM_ID_MAX
-};
-
-struct  tuner_custom_parameter_s {
-	uint16_t	param_id;	 /*  Parameter identifier  */
-	uint16_t	param_value;	 /*  Parameter value	   */
-};
-
-struct  tuner_ber_rate_s {
-	uint32_t	ber_rate;  /*  BER sample rate in seconds   */
-};
-
-struct tuner_atv_sig_stat_s {
-	uint32_t	sig_present;
-	uint32_t	sig_locked;
-	uint32_t	sig_lock_busy;
-	uint32_t	sig_strength;	   /*  milliDb	  */
-	uint32_t	tv_audio_chan;	  /*  mono/stereo/sap*/
-	uint32_t 	mvision_stat;	   /*  macrovision status */
-};
-
-struct tuner_dtv_sig_stat_s {
-	uint32_t sig_present;   /*  Boolean*/
-	uint32_t sig_locked;	/*  Boolean */
-	uint32_t sig_lock_busy; /*  Boolean	(Can this time-out?) */
-	uint32_t sig_strength;  /*  milliDb*/
-};
-
-struct tuner_fm_sig_stat_s {
-	uint32_t sig_present;	/* Boolean*/
-	uint32_t sig_locked;	 /* Boolean */
-	uint32_t sig_lock_busy;  /* Boolean */
-	uint32_t sig_stereo_mono;/* TBD*/
-	uint32_t sig_strength;   /* milliDb*/
-};
-
-enum _tag_tlg_tune_srv_cmd {
-	TLG_TUNE_PLAY_SVC_START = 1,
-	TLG_TUNE_PLAY_SVC_STOP
-};
-
-enum  _tag_tune_atv_audio_mode_caps {
-	TLG_TUNE_TVAUDIO_MODE_MONO	= 0x00000001,
-	TLG_TUNE_TVAUDIO_MODE_STEREO	= 0x00000002,
-	TLG_TUNE_TVAUDIO_MODE_LANG_A	= 0x00000010,/* Primary language*/
-	TLG_TUNE_TVAUDIO_MODE_LANG_B	= 0x00000020,/* 2nd avail language*/
-	TLG_TUNE_TVAUDIO_MODE_LANG_C	= 0x00000040
-};
-
-
-enum   _tag_tuner_atv_audio_rates {
-	ATV_AUDIO_RATE_NONE	= 0x00,/* Audio not supported*/
-	ATV_AUDIO_RATE_32K	= 0x01,/* Audio rate = 32 KHz*/
-	ATV_AUDIO_RATE_48K	= 0x02, /* Audio rate = 48 KHz*/
-	ATV_AUDIO_RATE_31_25K	= 0x04 /* Audio rate = 31.25KHz */
-};
-
-enum  _tag_tune_atv_vid_res_caps {
-	TLG_TUNE_VID_RES_NONE	= 0x00000000,
-	TLG_TUNE_VID_RES_720	= 0x00000001,
-	TLG_TUNE_VID_RES_704	= 0x00000002,
-	TLG_TUNE_VID_RES_360	= 0x00000004
-};
-
-enum _tag_tuner_analog_video_format {
-	TLG_TUNER_VID_FORMAT_YUV	= 0x00000001,
-	TLG_TUNER_VID_FORMAT_YCRCB	= 0x00000002,
-	TLG_TUNER_VID_FORMAT_RGB_565	= 0x00000004,
-};
-
-enum  tlg_ext_audio_support {
-	TLG_EXT_AUDIO_NONE 	= 0x00,/*  No external audio input supported */
-	TLG_EXT_AUDIO_LR	= 0x01/*  LR external audio inputs supported*/
-};
-
-enum {
-	TLG_MODE_NONE			= 0x00, /* No Mode specified*/
-	TLG_MODE_ANALOG_TV		= 0x01, /* Analog Television mode*/
-	TLG_MODE_ANALOG_TV_UNCOMP	= 0x01, /* Analog Television mode*/
-	TLG_MODE_ANALOG_TV_COMP  	= 0x02, /* Analog TV mode (compressed)*/
-	TLG_MODE_FM_RADIO		= 0x04, /* FM Radio mode*/
-	TLG_MODE_DVB_T			= 0x08, /* Digital TV (DVB-T)*/
-};
-
-enum  tlg_signal_sources_t {
-	TLG_SIG_SRC_NONE	= 0x00,/* Signal source not specified */
-	TLG_SIG_SRC_ANTENNA	= 0x01,/* Signal src is: Antenna */
-	TLG_SIG_SRC_CABLE	= 0x02,/* Signal src is: Coax Cable*/
-	TLG_SIG_SRC_SVIDEO	= 0x04,/* Signal src is: S_VIDEO   */
-	TLG_SIG_SRC_COMPOSITE   = 0x08 /* Signal src is: Composite Video */
-};
-
-enum tuner_analog_video_standard {
-	TLG_TUNE_VSTD_NONE	= 0x00000000,
-	TLG_TUNE_VSTD_NTSC_M	= 0x00000001,
-	TLG_TUNE_VSTD_NTSC_M_J	= 0x00000002,/* Japan   */
-	TLG_TUNE_VSTD_PAL_B	= 0x00000010,
-	TLG_TUNE_VSTD_PAL_D	= 0x00000020,
-	TLG_TUNE_VSTD_PAL_G	= 0x00000040,
-	TLG_TUNE_VSTD_PAL_H	= 0x00000080,
-	TLG_TUNE_VSTD_PAL_I	= 0x00000100,
-	TLG_TUNE_VSTD_PAL_M	= 0x00000200,
-	TLG_TUNE_VSTD_PAL_N	= 0x00000400,
-	TLG_TUNE_VSTD_SECAM_B	= 0x00001000,
-	TLG_TUNE_VSTD_SECAM_D	= 0x00002000,
-	TLG_TUNE_VSTD_SECAM_G	= 0x00004000,
-	TLG_TUNE_VSTD_SECAM_H	= 0x00008000,
-	TLG_TUNE_VSTD_SECAM_K	= 0x00010000,
-	TLG_TUNE_VSTD_SECAM_K1	= 0x00020000,
-	TLG_TUNE_VSTD_SECAM_L	= 0x00040000,
-	TLG_TUNE_VSTD_SECAM_L1	= 0x00080000,
-	TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000
-};
-
-enum tlg_mode_caps {
-	TLG_MODE_CAPS_NONE		= 0x00,  /*  No Mode specified	*/
-	TLG_MODE_CAPS_ANALOG_TV_UNCOMP  = 0x01,  /*  Analog TV mode     */
-	TLG_MODE_CAPS_ANALOG_TV_COMP	= 0x02,  /*  Analog TV (compressed)*/
-	TLG_MODE_CAPS_FM_RADIO		= 0x04,  /*  FM Radio mode	*/
-	TLG_MODE_CAPS_DVB_T		= 0x08,  /*  Digital TV (DVB-T)	*/
-};
-
-enum poseidon_vendor_cmds {
-	LAST_CMD_STAT		= 0x00,
-	GET_CHIP_ID		= 0x01,
-	GET_FW_ID		= 0x02,
-	PRODUCT_CAPS		= 0x03,
-
-	TUNE_MODE_CAP_ATV	= 0x10,
-	TUNE_MODE_CAP_ATVCOMP	= 0X10,
-	TUNE_MODE_CAP_DVBT	= 0x10,
-	TUNE_MODE_CAP_FM	= 0x10,
-	TUNE_MODE_SELECT	= 0x11,
-	TUNE_FREQ_SELECT	= 0x12,
-	SGNL_SRC_SEL		= 0x13,
-
-	VIDEO_STD_SEL		= 0x14,
-	VIDEO_STREAM_FMT_SEL	= 0x15,
-	VIDEO_ROSOLU_AVAIL	= 0x16,
-	VIDEO_ROSOLU_SEL	= 0x17,
-	VIDEO_CONT_PROTECT	= 0x20,
-
-	VCR_TIMING_MODSEL	= 0x21,
-	EXT_AUDIO_CAP		= 0x22,
-	EXT_AUDIO_SEL		= 0x23,
-	TEST_PATTERN_SEL	= 0x24,
-	VBI_DATA_SEL		= 0x25,
-	AUDIO_SAMPLE_RATE_CAP   = 0x28,
-	AUDIO_SAMPLE_RATE_SEL   = 0x29,
-	TUNER_AUD_MODE		= 0x2a,
-	TUNER_AUD_MODE_AVAIL	= 0x2b,
-	TUNER_AUD_ANA_STD	= 0x2c,
-	TUNER_CUSTOM_PARAMETER	= 0x2f,
-
-	DVBT_TUNE_MODE_SEL	= 0x30,
-	DVBT_BANDW_CAP		= 0x31,
-	DVBT_BANDW_SEL		= 0x32,
-	DVBT_GUARD_INTERV_CAP   = 0x33,
-	DVBT_GUARD_INTERV_SEL   = 0x34,
-	DVBT_MODULATION_CAP	= 0x35,
-	DVBT_MODULATION_SEL	= 0x36,
-	DVBT_INNER_FEC_RATE_CAP = 0x37,
-	DVBT_INNER_FEC_RATE_SEL = 0x38,
-	DVBT_TRANS_MODE_CAP	= 0x39,
-	DVBT_TRANS_MODE_SEL	= 0x3a,
-	DVBT_SEARCH_RANG	= 0x3c,
-
-	TUNER_SETUP_ANALOG	= 0x40,
-	TUNER_SETUP_DIGITAL	= 0x41,
-	TUNER_SETUP_FM_RADIO	= 0x42,
-	TAKE_REQUEST		= 0x43, /* Take effect of the command */
-	PLAY_SERVICE		= 0x44, /* Play start or Play stop */
-	TUNER_STATUS		= 0x45,
-	TUNE_PROP_DVBT		= 0x46,
-	ERR_RATE_STATS		= 0x47,
-	TUNER_BER_RATE		= 0x48,
-
-	SCAN_CAPS		= 0x50,
-	SCAN_SETUP		= 0x51,
-	SCAN_SERVICE		= 0x52,
-	SCAN_STATS		= 0x53,
-
-	PID_SET			= 0x58,
-	PID_UNSET		= 0x59,
-	PID_LIST		= 0x5a,
-
-	IRD_CAP			= 0x60,
-	IRD_MODE_SEL		= 0x61,
-	IRD_SETUP		= 0x62,
-
-	PTM_MODE_CAP		= 0x70,
-	PTM_MODE_SEL		= 0x71,
-	PTM_SERVICE		= 0x72,
-	TUNER_REG_SCRIPT	= 0x73,
-	CMD_CHIP_RST		= 0x74,
-};
-
-enum tlg_bw {
-	TLG_BW_5 = 5,
-	TLG_BW_6 = 6,
-	TLG_BW_7 = 7,
-	TLG_BW_8 = 8,
-	TLG_BW_12 = 12,
-	TLG_BW_15 = 15
-};
-
-struct cmd_firmware_vers_s {
-	uint8_t	 fw_rev_major;
-	uint8_t	 fw_rev_minor;
-	uint16_t fw_patch;
-};
-#endif /* VENDOR_CMD_H_ */
diff --git a/drivers/staging/media/vino/Kconfig b/drivers/staging/media/vino/Kconfig
deleted file mode 100644
index 03700dadafd8..000000000000
--- a/drivers/staging/media/vino/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
-config VIDEO_VINO
-	tristate "SGI Vino Video For Linux (Deprecated)"
-	depends on I2C && SGI_IP22 && VIDEO_V4L2
-	select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT
-	help
-	  Say Y here to build in support for the Vino video input system found
-	  on SGI Indy machines.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-
-config VIDEO_SAA7191
-	tristate "Philips SAA7191 video decoder (Deprecated)"
-	depends on VIDEO_V4L2 && I2C
-	---help---
-	  Support for the Philips SAA7191 video decoder.
-
-	  This driver is deprecated and will be removed soon. If you have
-	  hardware for this and you want to work on this driver, then contact
-	  the linux-media mailinglist.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called saa7191.
diff --git a/drivers/staging/media/vino/Makefile b/drivers/staging/media/vino/Makefile
deleted file mode 100644
index 914c2513687c..000000000000
--- a/drivers/staging/media/vino/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_VIDEO_VINO) += indycam.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o
-obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
diff --git a/drivers/staging/media/vino/indycam.c b/drivers/staging/media/vino/indycam.c
deleted file mode 100644
index f1d192bbcb4c..000000000000
--- a/drivers/staging/media/vino/indycam.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- *  indycam.c - Silicon Graphics IndyCam digital camera driver
- *
- *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
- *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
- *
- *  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 <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-/* IndyCam decodes stream of photons into digital image representation ;-) */
-#include <linux/videodev2.h>
-#include <linux/i2c.h>
-#include <media/v4l2-device.h>
-
-#include "indycam.h"
-
-#define INDYCAM_MODULE_VERSION "0.0.5"
-
-MODULE_DESCRIPTION("SGI IndyCam driver");
-MODULE_VERSION(INDYCAM_MODULE_VERSION);
-MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
-MODULE_LICENSE("GPL");
-
-
-// #define INDYCAM_DEBUG
-
-#ifdef INDYCAM_DEBUG
-#define dprintk(x...) printk("IndyCam: " x);
-#define indycam_regdump(client) indycam_regdump_debug(client)
-#else
-#define dprintk(x...)
-#define indycam_regdump(client)
-#endif
-
-struct indycam {
-	struct v4l2_subdev sd;
-	u8 version;
-};
-
-static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct indycam, sd);
-}
-
-static const u8 initseq[] = {
-	INDYCAM_CONTROL_AGCENA,		/* INDYCAM_CONTROL */
-	INDYCAM_SHUTTER_60,		/* INDYCAM_SHUTTER */
-	INDYCAM_GAIN_DEFAULT,		/* INDYCAM_GAIN */
-	0x00,				/* INDYCAM_BRIGHTNESS (read-only) */
-	INDYCAM_RED_BALANCE_DEFAULT,	/* INDYCAM_RED_BALANCE */
-	INDYCAM_BLUE_BALANCE_DEFAULT,	/* INDYCAM_BLUE_BALANCE */
-	INDYCAM_RED_SATURATION_DEFAULT,	/* INDYCAM_RED_SATURATION */
-	INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
-};
-
-/* IndyCam register handling */
-
-static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	int ret;
-
-	if (reg == INDYCAM_REG_RESET) {
-		dprintk("indycam_read_reg(): "
-			"skipping write-only register %d\n", reg);
-		*value = 0;
-		return 0;
-	}
-
-	ret = i2c_smbus_read_byte_data(client, reg);
-
-	if (ret < 0) {
-		printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
-		       "register = 0x%02x\n", reg);
-		return ret;
-	}
-
-	*value = (u8)ret;
-
-	return 0;
-}
-
-static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	int err;
-
-	if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
-		dprintk("indycam_write_reg(): "
-			"skipping read-only register %d\n", reg);
-		return 0;
-	}
-
-	dprintk("Writing Reg %d = 0x%02x\n", reg, value);
-	err = i2c_smbus_write_byte_data(client, reg, value);
-
-	if (err) {
-		printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
-		       "register = 0x%02x, value = 0x%02x\n", reg, value);
-	}
-	return err;
-}
-
-static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
-			       u8 length, u8 *data)
-{
-	int i, err;
-
-	for (i = 0; i < length; i++) {
-		err = indycam_write_reg(sd, reg + i, data[i]);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-/* Helper functions */
-
-#ifdef INDYCAM_DEBUG
-static void indycam_regdump_debug(struct v4l2_subdev *sd)
-{
-	int i;
-	u8 val;
-
-	for (i = 0; i < 9; i++) {
-		indycam_read_reg(sd, i, &val);
-		dprintk("Reg %d = 0x%02x\n", i, val);
-	}
-}
-#endif
-
-static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct indycam *camera = to_indycam(sd);
-	u8 reg;
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUTOGAIN:
-	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
-		if (ret)
-			return -EIO;
-		if (ctrl->id == V4L2_CID_AUTOGAIN)
-			ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
-				? 1 : 0;
-		else
-			ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
-				? 1 : 0;
-		break;
-	case V4L2_CID_EXPOSURE:
-		ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, &reg);
-		if (ret)
-			return -EIO;
-		ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
-		break;
-	case V4L2_CID_GAIN:
-		ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, &reg);
-		if (ret)
-			return -EIO;
-		ctrl->value = (s32)reg;
-		break;
-	case V4L2_CID_RED_BALANCE:
-		ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, &reg);
-		if (ret)
-			return -EIO;
-		ctrl->value = (s32)reg;
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, &reg);
-		if (ret)
-			return -EIO;
-		ctrl->value = (s32)reg;
-		break;
-	case INDYCAM_CONTROL_RED_SATURATION:
-		ret = indycam_read_reg(sd,
-				       INDYCAM_REG_RED_SATURATION, &reg);
-		if (ret)
-			return -EIO;
-		ctrl->value = (s32)reg;
-		break;
-	case INDYCAM_CONTROL_BLUE_SATURATION:
-		ret = indycam_read_reg(sd,
-				       INDYCAM_REG_BLUE_SATURATION, &reg);
-		if (ret)
-			return -EIO;
-		ctrl->value = (s32)reg;
-		break;
-	case V4L2_CID_GAMMA:
-		if (camera->version == CAMERA_VERSION_MOOSE) {
-			ret = indycam_read_reg(sd,
-					       INDYCAM_REG_GAMMA, &reg);
-			if (ret)
-				return -EIO;
-			ctrl->value = (s32)reg;
-		} else {
-			ctrl->value = INDYCAM_GAMMA_DEFAULT;
-		}
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct indycam *camera = to_indycam(sd);
-	u8 reg;
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUTOGAIN:
-	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
-		if (ret)
-			break;
-
-		if (ctrl->id == V4L2_CID_AUTOGAIN) {
-			if (ctrl->value)
-				reg |= INDYCAM_CONTROL_AGCENA;
-			else
-				reg &= ~INDYCAM_CONTROL_AGCENA;
-		} else {
-			if (ctrl->value)
-				reg |= INDYCAM_CONTROL_AWBCTL;
-			else
-				reg &= ~INDYCAM_CONTROL_AWBCTL;
-		}
-
-		ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
-		break;
-	case V4L2_CID_EXPOSURE:
-		reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
-		ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
-		break;
-	case V4L2_CID_GAIN:
-		ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
-					ctrl->value);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
-					ctrl->value);
-		break;
-	case INDYCAM_CONTROL_RED_SATURATION:
-		ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
-					ctrl->value);
-		break;
-	case INDYCAM_CONTROL_BLUE_SATURATION:
-		ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
-					ctrl->value);
-		break;
-	case V4L2_CID_GAMMA:
-		if (camera->version == CAMERA_VERSION_MOOSE) {
-			ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
-						ctrl->value);
-		}
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-/* I2C-interface */
-
-/* ----------------------------------------------------------------------- */
-
-static const struct v4l2_subdev_core_ops indycam_core_ops = {
-	.g_ctrl = indycam_g_ctrl,
-	.s_ctrl = indycam_s_ctrl,
-};
-
-static const struct v4l2_subdev_ops indycam_ops = {
-	.core = &indycam_core_ops,
-};
-
-static int indycam_probe(struct i2c_client *client,
-			  const struct i2c_device_id *id)
-{
-	int err = 0;
-	struct indycam *camera;
-	struct v4l2_subdev *sd;
-
-	v4l_info(client, "chip found @ 0x%x (%s)\n",
-			client->addr << 1, client->adapter->name);
-
-	camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
-	if (!camera)
-		return -ENOMEM;
-
-	sd = &camera->sd;
-	v4l2_i2c_subdev_init(sd, client, &indycam_ops);
-
-	camera->version = i2c_smbus_read_byte_data(client,
-						   INDYCAM_REG_VERSION);
-	if (camera->version != CAMERA_VERSION_INDY &&
-	    camera->version != CAMERA_VERSION_MOOSE) {
-		kfree(camera);
-		return -ENODEV;
-	}
-
-	printk(KERN_INFO "IndyCam v%d.%d detected\n",
-	       INDYCAM_VERSION_MAJOR(camera->version),
-	       INDYCAM_VERSION_MINOR(camera->version));
-
-	indycam_regdump(sd);
-
-	// initialize
-	err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
-	if (err) {
-		printk(KERN_ERR "IndyCam initialization failed\n");
-		kfree(camera);
-		return -EIO;
-	}
-
-	indycam_regdump(sd);
-
-	// white balance
-	err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
-			  INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
-	if (err) {
-		printk(KERN_ERR "IndyCam: White balancing camera failed\n");
-		kfree(camera);
-		return -EIO;
-	}
-
-	indycam_regdump(sd);
-
-	printk(KERN_INFO "IndyCam initialized\n");
-
-	return 0;
-}
-
-static int indycam_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-	v4l2_device_unregister_subdev(sd);
-	kfree(to_indycam(sd));
-	return 0;
-}
-
-static const struct i2c_device_id indycam_id[] = {
-	{ "indycam", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, indycam_id);
-
-static struct i2c_driver indycam_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "indycam",
-	},
-	.probe		= indycam_probe,
-	.remove		= indycam_remove,
-	.id_table	= indycam_id,
-};
-
-module_i2c_driver(indycam_driver);
diff --git a/drivers/staging/media/vino/indycam.h b/drivers/staging/media/vino/indycam.h
deleted file mode 100644
index 881f21c474c4..000000000000
--- a/drivers/staging/media/vino/indycam.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *  indycam.h - Silicon Graphics IndyCam digital camera driver
- *
- *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
- *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
- *
- *  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 _INDYCAM_H_
-#define _INDYCAM_H_
-
-/* I2C address for the Guinness Camera */
-#define INDYCAM_ADDR			0x56
-
-/* Camera version */
-#define CAMERA_VERSION_INDY		0x10	/* v1.0 */
-#define CAMERA_VERSION_MOOSE		0x12	/* v1.2 */
-#define INDYCAM_VERSION_MAJOR(x)	(((x) & 0xf0) >> 4)
-#define INDYCAM_VERSION_MINOR(x)	((x) & 0x0f)
-
-/* Register bus addresses */
-#define INDYCAM_REG_CONTROL		0x00
-#define INDYCAM_REG_SHUTTER		0x01
-#define INDYCAM_REG_GAIN		0x02
-#define INDYCAM_REG_BRIGHTNESS		0x03 /* read-only */
-#define INDYCAM_REG_RED_BALANCE		0x04
-#define INDYCAM_REG_BLUE_BALANCE	0x05
-#define INDYCAM_REG_RED_SATURATION	0x06
-#define INDYCAM_REG_BLUE_SATURATION	0x07
-#define INDYCAM_REG_GAMMA		0x08
-#define INDYCAM_REG_VERSION		0x0e /* read-only */
-#define INDYCAM_REG_RESET		0x0f /* write-only */
-
-#define INDYCAM_REG_LED			0x46
-#define INDYCAM_REG_ORIENTATION		0x47
-#define INDYCAM_REG_BUTTON		0x48
-
-/* Field definitions of registers */
-#define INDYCAM_CONTROL_AGCENA		(1<<0) /* automatic gain control */
-#define INDYCAM_CONTROL_AWBCTL		(1<<1) /* automatic white balance */
-						/* 2-3 are reserved */
-#define INDYCAM_CONTROL_EVNFLD		(1<<4)	/* read-only */
-
-#define INDYCAM_SHUTTER_10000		0x02	/* 1/10000 second */
-#define INDYCAM_SHUTTER_4000		0x04	/* 1/4000 second */
-#define INDYCAM_SHUTTER_2000		0x08	/* 1/2000 second */
-#define INDYCAM_SHUTTER_1000		0x10	/* 1/1000 second */
-#define INDYCAM_SHUTTER_500		0x20	/* 1/500 second */
-#define INDYCAM_SHUTTER_250		0x3f	/* 1/250 second */
-#define INDYCAM_SHUTTER_125		0x7e	/* 1/125 second */
-#define INDYCAM_SHUTTER_100		0x9e	/* 1/100 second */
-#define INDYCAM_SHUTTER_60		0x00	/* 1/60 second */
-
-#define INDYCAM_LED_ACTIVE			0x10
-#define INDYCAM_LED_INACTIVE			0x30
-#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP	0x40
-#define INDYCAM_BUTTON_RELEASED			0x10
-
-/* Values for controls */
-#define INDYCAM_SHUTTER_MIN		0x00
-#define INDYCAM_SHUTTER_MAX		0xff
-#define INDYCAM_GAIN_MIN                0x00
-#define INDYCAM_GAIN_MAX                0xff
-#define INDYCAM_RED_BALANCE_MIN		0x00
-#define INDYCAM_RED_BALANCE_MAX		0xff
-#define INDYCAM_BLUE_BALANCE_MIN        0x00
-#define INDYCAM_BLUE_BALANCE_MAX        0xff
-#define INDYCAM_RED_SATURATION_MIN      0x00
-#define INDYCAM_RED_SATURATION_MAX      0xff
-#define INDYCAM_BLUE_SATURATION_MIN	0x00
-#define INDYCAM_BLUE_SATURATION_MAX	0xff
-#define INDYCAM_GAMMA_MIN		0x00
-#define INDYCAM_GAMMA_MAX		0xff
-
-#define INDYCAM_AGC_DEFAULT		1
-#define INDYCAM_AWB_DEFAULT		0
-#define INDYCAM_SHUTTER_DEFAULT		0xff
-#define INDYCAM_GAIN_DEFAULT		0x80
-#define INDYCAM_RED_BALANCE_DEFAULT	0x18
-#define INDYCAM_BLUE_BALANCE_DEFAULT	0xa4
-#define INDYCAM_RED_SATURATION_DEFAULT	0x80
-#define INDYCAM_BLUE_SATURATION_DEFAULT	0xc0
-#define INDYCAM_GAMMA_DEFAULT		0x80
-
-/* Driver interface definitions */
-
-#define INDYCAM_CONTROL_RED_SATURATION		(V4L2_CID_PRIVATE_BASE + 0)
-#define INDYCAM_CONTROL_BLUE_SATURATION		(V4L2_CID_PRIVATE_BASE + 1)
-
-#endif
diff --git a/drivers/staging/media/vino/saa7191.c b/drivers/staging/media/vino/saa7191.c
deleted file mode 100644
index 8e9699268a63..000000000000
--- a/drivers/staging/media/vino/saa7191.c
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- *  saa7191.c - Philips SAA7191 video decoder driver
- *
- *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
- *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
- *
- *  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 <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <linux/videodev2.h>
-#include <linux/i2c.h>
-#include <media/v4l2-device.h>
-
-#include "saa7191.h"
-
-#define SAA7191_MODULE_VERSION	"0.0.5"
-
-MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
-MODULE_VERSION(SAA7191_MODULE_VERSION);
-MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
-MODULE_LICENSE("GPL");
-
-
-// #define SAA7191_DEBUG
-
-#ifdef SAA7191_DEBUG
-#define dprintk(x...) printk("SAA7191: " x);
-#else
-#define dprintk(x...)
-#endif
-
-#define SAA7191_SYNC_COUNT	30
-#define SAA7191_SYNC_DELAY	100	/* milliseconds */
-
-struct saa7191 {
-	struct v4l2_subdev sd;
-
-	/* the register values are stored here as the actual
-	 * I2C-registers are write-only */
-	u8 reg[25];
-
-	int input;
-	v4l2_std_id norm;
-};
-
-static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct saa7191, sd);
-}
-
-static const u8 initseq[] = {
-	0,	/* Subaddress */
-
-	0x50,	/* (0x50) SAA7191_REG_IDEL */
-
-	/* 50 Hz signal timing */
-	0x30,	/* (0x30) SAA7191_REG_HSYB */
-	0x00,	/* (0x00) SAA7191_REG_HSYS */
-	0xe8,	/* (0xe8) SAA7191_REG_HCLB */
-	0xb6,	/* (0xb6) SAA7191_REG_HCLS */
-	0xf4,	/* (0xf4) SAA7191_REG_HPHI */
-
-	/* control */
-	SAA7191_LUMA_APER_1,	/* (0x01) SAA7191_REG_LUMA - CVBS mode */
-	0x00,	/* (0x00) SAA7191_REG_HUEC */
-	0xf8,	/* (0xf8) SAA7191_REG_CKTQ */
-	0xf8,	/* (0xf8) SAA7191_REG_CKTS */
-	0x90,	/* (0x90) SAA7191_REG_PLSE */
-	0x90,	/* (0x90) SAA7191_REG_SESE */
-	0x00,	/* (0x00) SAA7191_REG_GAIN */
-	SAA7191_STDC_NFEN | SAA7191_STDC_HRMV,	/* (0x0c) SAA7191_REG_STDC
-						 * - not SECAM,
-						 * slow time constant */
-	SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS
-	| SAA7191_IOCK_OEDY,	/* (0x78) SAA7191_REG_IOCK
-				 * - chroma from CVBS, GPSW1 & 2 off */
-	SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS
-	| SAA7191_CTL3_YDEL0,	/* (0x99) SAA7191_REG_CTL3
-				 * - automatic field detection */
-	0x00,	/* (0x00) SAA7191_REG_CTL4 */
-	0x2c,	/* (0x2c) SAA7191_REG_CHCV - PAL nominal value */
-	0x00,	/* unused */
-	0x00,	/* unused */
-
-	/* 60 Hz signal timing */
-	0x34,	/* (0x34) SAA7191_REG_HS6B */
-	0x0a,	/* (0x0a) SAA7191_REG_HS6S */
-	0xf4,	/* (0xf4) SAA7191_REG_HC6B */
-	0xce,	/* (0xce) SAA7191_REG_HC6S */
-	0xf4,	/* (0xf4) SAA7191_REG_HP6I */
-};
-
-/* SAA7191 register handling */
-
-static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
-{
-	return to_saa7191(sd)->reg[reg];
-}
-
-static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	int ret;
-
-	ret = i2c_master_recv(client, value, 1);
-	if (ret < 0) {
-		printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-
-static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	to_saa7191(sd)->reg[reg] = value;
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-/* the first byte of data must be the first subaddress number (register) */
-static int saa7191_write_block(struct v4l2_subdev *sd,
-			       u8 length, const u8 *data)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct saa7191 *decoder = to_saa7191(sd);
-	int i;
-	int ret;
-
-	for (i = 0; i < (length - 1); i++) {
-		decoder->reg[data[0] + i] = data[i + 1];
-	}
-
-	ret = i2c_master_send(client, data, length);
-	if (ret < 0) {
-		printk(KERN_ERR "SAA7191: saa7191_write_block(): "
-		       "write failed\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-/* Helper functions */
-
-static int saa7191_s_routing(struct v4l2_subdev *sd,
-			     u32 input, u32 output, u32 config)
-{
-	struct saa7191 *decoder = to_saa7191(sd);
-	u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA);
-	u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK);
-	int err;
-
-	switch (input) {
-	case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
-		iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
-			  | SAA7191_IOCK_GPSW2);
-		/* Chrominance trap active */
-		luma &= ~SAA7191_LUMA_BYPS;
-		break;
-	case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
-		iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
-		/* Chrominance trap bypassed */
-		luma |= SAA7191_LUMA_BYPS;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
-	if (err)
-		return -EIO;
-	err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
-	if (err)
-		return -EIO;
-
-	decoder->input = input;
-
-	return 0;
-}
-
-static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-	struct saa7191 *decoder = to_saa7191(sd);
-	u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
-	u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
-	u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV);
-	int err;
-
-	if (norm & V4L2_STD_PAL) {
-		stdc &= ~SAA7191_STDC_SECS;
-		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
-		chcv = SAA7191_CHCV_PAL;
-	} else if (norm & V4L2_STD_NTSC) {
-		stdc &= ~SAA7191_STDC_SECS;
-		ctl3 &= ~SAA7191_CTL3_AUFD;
-		ctl3 |= SAA7191_CTL3_FSEL;
-		chcv = SAA7191_CHCV_NTSC;
-	} else if (norm & V4L2_STD_SECAM) {
-		stdc |= SAA7191_STDC_SECS;
-		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
-		chcv = SAA7191_CHCV_PAL;
-	} else {
-		return -EINVAL;
-	}
-
-	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
-	if (err)
-		return -EIO;
-	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
-	if (err)
-		return -EIO;
-	err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
-	if (err)
-		return -EIO;
-
-	decoder->norm = norm;
-
-	dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
-		stdc, chcv);
-	dprintk("norm: %llx\n", norm);
-
-	return 0;
-}
-
-static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status)
-{
-	int i = 0;
-
-	dprintk("Checking for signal...\n");
-
-	for (i = 0; i < SAA7191_SYNC_COUNT; i++) {
-		if (saa7191_read_status(sd, status))
-			return -EIO;
-
-		if (((*status) & SAA7191_STATUS_HLCK) == 0) {
-			dprintk("Signal found\n");
-			return 0;
-		}
-
-		msleep(SAA7191_SYNC_DELAY);
-	}
-
-	dprintk("No signal\n");
-
-	return -EBUSY;
-}
-
-static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
-{
-	struct saa7191 *decoder = to_saa7191(sd);
-	u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
-	u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
-	u8 status;
-	v4l2_std_id old_norm = decoder->norm;
-	int err = 0;
-
-	dprintk("SAA7191 extended signal auto-detection...\n");
-
-	*norm &= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
-	stdc &= ~SAA7191_STDC_SECS;
-	ctl3 &= ~(SAA7191_CTL3_FSEL);
-
-	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
-	if (err) {
-		err = -EIO;
-		goto out;
-	}
-	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
-	if (err) {
-		err = -EIO;
-		goto out;
-	}
-
-	ctl3 |= SAA7191_CTL3_AUFD;
-	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
-	if (err) {
-		err = -EIO;
-		goto out;
-	}
-
-	msleep(SAA7191_SYNC_DELAY);
-
-	err = saa7191_wait_for_signal(sd, &status);
-	if (err)
-		goto out;
-
-	if (status & SAA7191_STATUS_FIDT) {
-		/* 60Hz signal -> NTSC */
-		dprintk("60Hz signal: NTSC\n");
-		*norm &= V4L2_STD_NTSC;
-		return 0;
-	}
-
-	/* 50Hz signal */
-	dprintk("50Hz signal: Trying PAL...\n");
-
-	/* try PAL first */
-	err = saa7191_s_std(sd, V4L2_STD_PAL);
-	if (err)
-		goto out;
-
-	msleep(SAA7191_SYNC_DELAY);
-
-	err = saa7191_wait_for_signal(sd, &status);
-	if (err)
-		goto out;
-
-	/* not 50Hz ? */
-	if (status & SAA7191_STATUS_FIDT) {
-		dprintk("No 50Hz signal\n");
-		saa7191_s_std(sd, old_norm);
-		*norm = V4L2_STD_UNKNOWN;
-		return 0;
-	}
-
-	if (status & SAA7191_STATUS_CODE) {
-		dprintk("PAL\n");
-		*norm &= V4L2_STD_PAL;
-		return saa7191_s_std(sd, old_norm);
-	}
-
-	dprintk("No color detected with PAL - Trying SECAM...\n");
-
-	/* no color detected ? -> try SECAM */
-	err = saa7191_s_std(sd, V4L2_STD_SECAM);
-	if (err)
-		goto out;
-
-	msleep(SAA7191_SYNC_DELAY);
-
-	err = saa7191_wait_for_signal(sd, &status);
-	if (err)
-		goto out;
-
-	/* not 50Hz ? */
-	if (status & SAA7191_STATUS_FIDT) {
-		dprintk("No 50Hz signal\n");
-		*norm = V4L2_STD_UNKNOWN;
-		goto out;
-	}
-
-	if (status & SAA7191_STATUS_CODE) {
-		/* Color detected -> SECAM */
-		dprintk("SECAM\n");
-		*norm &= V4L2_STD_SECAM;
-		return saa7191_s_std(sd, old_norm);
-	}
-
-	dprintk("No color detected with SECAM - Going back to PAL.\n");
-	*norm = V4L2_STD_UNKNOWN;
-
-out:
-	return saa7191_s_std(sd, old_norm);
-}
-
-static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
-{
-	u8 status;
-
-	dprintk("SAA7191 signal auto-detection...\n");
-
-	dprintk("Reading status...\n");
-
-	if (saa7191_read_status(sd, &status))
-		return -EIO;
-
-	dprintk("Checking for signal...\n");
-
-	/* no signal ? */
-	if (status & SAA7191_STATUS_HLCK) {
-		dprintk("No signal\n");
-		return -EBUSY;
-	}
-
-	dprintk("Signal found\n");
-
-	if (status & SAA7191_STATUS_FIDT) {
-		/* 60hz signal -> NTSC */
-		dprintk("NTSC\n");
-		return saa7191_s_std(sd, V4L2_STD_NTSC);
-	} else {
-		/* 50hz signal -> PAL */
-		dprintk("PAL\n");
-		return saa7191_s_std(sd, V4L2_STD_PAL);
-	}
-}
-
-static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	u8 reg;
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case SAA7191_CONTROL_BANDPASS:
-	case SAA7191_CONTROL_BANDPASS_WEIGHT:
-	case SAA7191_CONTROL_CORING:
-		reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
-		switch (ctrl->id) {
-		case SAA7191_CONTROL_BANDPASS:
-			ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)
-				>> SAA7191_LUMA_BPSS_SHIFT;
-			break;
-		case SAA7191_CONTROL_BANDPASS_WEIGHT:
-			ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK)
-				>> SAA7191_LUMA_APER_SHIFT;
-			break;
-		case SAA7191_CONTROL_CORING:
-			ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK)
-				>> SAA7191_LUMA_CORI_SHIFT;
-			break;
-		}
-		break;
-	case SAA7191_CONTROL_FORCE_COLOUR:
-	case SAA7191_CONTROL_CHROMA_GAIN:
-		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
-		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR)
-			ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;
-		else
-			ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)
-				>> SAA7191_GAIN_LFIS_SHIFT;
-		break;
-	case V4L2_CID_HUE:
-		reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
-		if (reg < 0x80)
-			reg += 0x80;
-		else
-			reg -= 0x80;
-		ctrl->value = (s32)reg;
-		break;
-	case SAA7191_CONTROL_VTRC:
-		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
-		ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;
-		break;
-	case SAA7191_CONTROL_LUMA_DELAY:
-		reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
-		ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)
-			>> SAA7191_CTL3_YDEL_SHIFT;
-		if (ctrl->value >= 4)
-			ctrl->value -= 8;
-		break;
-	case SAA7191_CONTROL_VNR:
-		reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
-		ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
-			>> SAA7191_CTL4_VNOI_SHIFT;
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	u8 reg;
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case SAA7191_CONTROL_BANDPASS:
-	case SAA7191_CONTROL_BANDPASS_WEIGHT:
-	case SAA7191_CONTROL_CORING:
-		reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
-		switch (ctrl->id) {
-		case SAA7191_CONTROL_BANDPASS:
-			reg &= ~SAA7191_LUMA_BPSS_MASK;
-			reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)
-				& SAA7191_LUMA_BPSS_MASK;
-			break;
-		case SAA7191_CONTROL_BANDPASS_WEIGHT:
-			reg &= ~SAA7191_LUMA_APER_MASK;
-			reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT)
-				& SAA7191_LUMA_APER_MASK;
-			break;
-		case SAA7191_CONTROL_CORING:
-			reg &= ~SAA7191_LUMA_CORI_MASK;
-			reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT)
-				& SAA7191_LUMA_CORI_MASK;
-			break;
-		}
-		ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
-		break;
-	case SAA7191_CONTROL_FORCE_COLOUR:
-	case SAA7191_CONTROL_CHROMA_GAIN:
-		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
-		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
-			if (ctrl->value)
-				reg |= SAA7191_GAIN_COLO;
-			else
-				reg &= ~SAA7191_GAIN_COLO;
-		} else {
-			reg &= ~SAA7191_GAIN_LFIS_MASK;
-			reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
-				& SAA7191_GAIN_LFIS_MASK;
-		}
-		ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
-		break;
-	case V4L2_CID_HUE:
-		reg = ctrl->value & 0xff;
-		if (reg < 0x80)
-			reg += 0x80;
-		else
-			reg -= 0x80;
-		ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
-		break;
-	case SAA7191_CONTROL_VTRC:
-		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
-		if (ctrl->value)
-			reg |= SAA7191_STDC_VTRC;
-		else
-			reg &= ~SAA7191_STDC_VTRC;
-		ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg);
-		break;
-	case SAA7191_CONTROL_LUMA_DELAY: {
-		s32 value = ctrl->value;
-		if (value < 0)
-			value += 8;
-		reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
-		reg &= ~SAA7191_CTL3_YDEL_MASK;
-		reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
-			& SAA7191_CTL3_YDEL_MASK;
-		ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
-		break;
-	}
-	case SAA7191_CONTROL_VNR:
-		reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
-		reg &= ~SAA7191_CTL4_VNOI_MASK;
-		reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)
-			& SAA7191_CTL4_VNOI_MASK;
-		ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-/* I2C-interface */
-
-static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status)
-{
-	u8 status_reg;
-	int res = V4L2_IN_ST_NO_SIGNAL;
-
-	if (saa7191_read_status(sd, &status_reg))
-		return -EIO;
-	if ((status_reg & SAA7191_STATUS_HLCK) == 0)
-		res = 0;
-	if (!(status_reg & SAA7191_STATUS_CODE))
-		res |= V4L2_IN_ST_NO_COLOR;
-	*status = res;
-	return 0;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-static const struct v4l2_subdev_core_ops saa7191_core_ops = {
-	.g_ctrl = saa7191_g_ctrl,
-	.s_ctrl = saa7191_s_ctrl,
-};
-
-static const struct v4l2_subdev_video_ops saa7191_video_ops = {
-	.s_std = saa7191_s_std,
-	.s_routing = saa7191_s_routing,
-	.querystd = saa7191_querystd,
-	.g_input_status = saa7191_g_input_status,
-};
-
-static const struct v4l2_subdev_ops saa7191_ops = {
-	.core = &saa7191_core_ops,
-	.video = &saa7191_video_ops,
-};
-
-static int saa7191_probe(struct i2c_client *client,
-			  const struct i2c_device_id *id)
-{
-	int err = 0;
-	struct saa7191 *decoder;
-	struct v4l2_subdev *sd;
-
-	v4l_info(client, "chip found @ 0x%x (%s)\n",
-			client->addr << 1, client->adapter->name);
-
-	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
-	if (!decoder)
-		return -ENOMEM;
-
-	sd = &decoder->sd;
-	v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
-
-	err = saa7191_write_block(sd, sizeof(initseq), initseq);
-	if (err) {
-		printk(KERN_ERR "SAA7191 initialization failed\n");
-		return err;
-	}
-
-	printk(KERN_INFO "SAA7191 initialized\n");
-
-	decoder->input = SAA7191_INPUT_COMPOSITE;
-	decoder->norm = V4L2_STD_PAL;
-
-	err = saa7191_autodetect_norm(sd);
-	if (err && (err != -EBUSY))
-		printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
-
-	return 0;
-}
-
-static int saa7191_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-	v4l2_device_unregister_subdev(sd);
-	return 0;
-}
-
-static const struct i2c_device_id saa7191_id[] = {
-	{ "saa7191", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, saa7191_id);
-
-static struct i2c_driver saa7191_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "saa7191",
-	},
-	.probe		= saa7191_probe,
-	.remove		= saa7191_remove,
-	.id_table	= saa7191_id,
-};
-
-module_i2c_driver(saa7191_driver);
diff --git a/drivers/staging/media/vino/saa7191.h b/drivers/staging/media/vino/saa7191.h
deleted file mode 100644
index 803c74d6066f..000000000000
--- a/drivers/staging/media/vino/saa7191.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- *  saa7191.h - Philips SAA7191 video decoder driver
- *
- *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
- *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
- *
- *  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 _SAA7191_H_
-#define _SAA7191_H_
-
-/* Philips SAA7191 DMSD I2C bus address */
-#define SAA7191_ADDR		0x8a
-
-/* Register subaddresses. */
-#define SAA7191_REG_IDEL	0x00
-#define SAA7191_REG_HSYB	0x01
-#define SAA7191_REG_HSYS	0x02
-#define SAA7191_REG_HCLB	0x03
-#define SAA7191_REG_HCLS	0x04
-#define SAA7191_REG_HPHI	0x05
-#define SAA7191_REG_LUMA	0x06
-#define SAA7191_REG_HUEC	0x07
-#define SAA7191_REG_CKTQ	0x08 /* bits 3-7 */
-#define SAA7191_REG_CKTS	0x09 /* bits 3-7 */
-#define SAA7191_REG_PLSE	0x0a
-#define SAA7191_REG_SESE	0x0b
-#define SAA7191_REG_GAIN	0x0c
-#define SAA7191_REG_STDC	0x0d
-#define SAA7191_REG_IOCK	0x0e
-#define SAA7191_REG_CTL3	0x0f
-#define SAA7191_REG_CTL4	0x10
-#define SAA7191_REG_CHCV	0x11
-#define SAA7191_REG_HS6B	0x14
-#define SAA7191_REG_HS6S	0x15
-#define SAA7191_REG_HC6B	0x16
-#define SAA7191_REG_HC6S	0x17
-#define SAA7191_REG_HP6I	0x18
-#define SAA7191_REG_STATUS	0xff	/* not really a subaddress */
-
-/* Status Register definitions */
-#define SAA7191_STATUS_CODE	0x01	/* color detected flag */
-#define SAA7191_STATUS_FIDT	0x20	/* signal type 50/60 Hz */
-#define SAA7191_STATUS_HLCK	0x40	/* PLL unlocked(1)/locked(0) */
-#define SAA7191_STATUS_STTC	0x80	/* tv/vtr time constant */
-
-/* Luminance Control Register definitions */
-/* input mode select bit:
- * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */
-#define SAA7191_LUMA_BYPS	0x80
-/* pre-filter (only when chrominance trap is active) */
-#define SAA7191_LUMA_PREF	0x40
-/* aperture bandpass to select different characteristics with maximums
- * (bits 4-5) */
-#define SAA7191_LUMA_BPSS_MASK	0x30
-#define SAA7191_LUMA_BPSS_SHIFT	4
-#define SAA7191_LUMA_BPSS_3	0x30
-#define SAA7191_LUMA_BPSS_2	0x20
-#define SAA7191_LUMA_BPSS_1	0x10
-#define SAA7191_LUMA_BPSS_0	0x00
-/* coring range for high frequency components according to 8-bit luminance
- * (bits 2-3)
- * 0=coring off, n= (+-)n LSB */
-#define SAA7191_LUMA_CORI_MASK	0x0c
-#define SAA7191_LUMA_CORI_SHIFT	2
-#define SAA7191_LUMA_CORI_3	0x0c
-#define SAA7191_LUMA_CORI_2	0x08
-#define SAA7191_LUMA_CORI_1	0x04
-#define SAA7191_LUMA_CORI_0	0x00
-/* aperture bandpass filter weights high frequency components of luminance
- * signal (bits 0-1)
- * 0=factor 0, 1=0.25, 2=0.5, 3=1 */
-#define SAA7191_LUMA_APER_MASK	0x03
-#define SAA7191_LUMA_APER_SHIFT	0
-#define SAA7191_LUMA_APER_3	0x03
-#define SAA7191_LUMA_APER_2	0x02
-#define SAA7191_LUMA_APER_1	0x01
-#define SAA7191_LUMA_APER_0	0x00
-
-/* Chrominance Gain Control Settings Register definitions */
-/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */
-#define SAA7191_GAIN_COLO	0x80
-/* chrominance gain control (AGC filter)
- * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */
-#define SAA7191_GAIN_LFIS_MASK	0x60
-#define SAA7191_GAIN_LFIS_SHIFT	5
-#define SAA7191_GAIN_LFIS_3	0x60
-#define SAA7191_GAIN_LFIS_2	0x40
-#define SAA7191_GAIN_LFIS_1	0x20
-#define SAA7191_GAIN_LFIS_0	0x00
-
-/* Standard/Mode Control Register definitions */
-/* tv/vtr mode bit: 0=TV mode (slow time constant),
- * 1=VTR mode (fast time constant) */
-#define SAA7191_STDC_VTRC	0x80
-/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs)
- * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */
-#define SAA7191_STDC_NFEN	0x08
-/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */
-#define SAA7191_STDC_HRMV	0x04
-/* general purpose switch 0
- * (not used with VINO afaik) */
-#define SAA7191_STDC_GPSW0	0x02
-/* SECAM mode bit: 0=other standards, 1=SECAM */
-#define SAA7191_STDC_SECS	0x01
-
-/* I/O and Clock Control Register definitions */
-/* horizontal clock PLL: 0=PLL closed,
- * 1=PLL circuit open and horizontal freq fixed */
-#define SAA7191_IOCK_HPLL	0x80
-/* colour-difference output enable (outputs UV0-UV7) */
-#define SAA7191_IOCK_OEDC	0x40
-/* H-sync output enable */
-#define SAA7191_IOCK_OEHS	0x20
-/* V-sync output enable */
-#define SAA7191_IOCK_OEVS	0x10
-/* luminance output enable (outputs Y0-Y7) */
-#define SAA7191_IOCK_OEDY	0x08
-/* S-VHS bit (chrominance from CVBS or from chrominance input):
- * 0=controlled by BYPS-bit, 1=from chrominance input */
-#define SAA7191_IOCK_CHRS	0x04
-/* general purpose switch 2
- * VINO-specific: 0=used with CVBS, 1=used with S-Video */
-#define SAA7191_IOCK_GPSW2	0x02
-/* general purpose switch 1 */
-/* VINO-specific: 0=always, 1=not used!*/
-#define SAA7191_IOCK_GPSW1	0x01
-
-/* Miscellaneous Control #1 Register definitions */
-/* automatic field detection (50/60Hz standard) */
-#define SAA7191_CTL3_AUFD	0x80
-/* field select: (if AUFD=0)
- * 0=50Hz (625 lines), 1=60Hz (525 lines) */
-#define SAA7191_CTL3_FSEL	0x40
-/* SECAM cross-colour reduction enable */
-#define SAA7191_CTL3_SXCR	0x20
-/* sync and clamping pulse enable (HCL and HSY outputs) */
-#define SAA7191_CTL3_SCEN	0x10
-/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */
-#define SAA7191_CTL3_OFTS	0x08
-/* luminance delay compensation
- * 0=0*2/LLC,  1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC,
- * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC
- * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */
-#define SAA7191_CTL3_YDEL_MASK	0x07
-#define SAA7191_CTL3_YDEL_SHIFT	0
-#define SAA7191_CTL3_YDEL2	0x04
-#define SAA7191_CTL3_YDEL1	0x02
-#define SAA7191_CTL3_YDEL0	0x01
-
-/* Miscellaneous Control #2 Register definitions */
-/* select HREF position
- * 0=normal, HREF is matched to YUV output port,
- * 1=HREF is matched to CVBS input port */
-#define SAA7191_CTL4_HRFS	0x04
-/* vertical noise reduction
- * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */
-#define SAA7191_CTL4_VNOI_MASK	0x03
-#define SAA7191_CTL4_VNOI_SHIFT	0
-#define SAA7191_CTL4_VNOI_3	0x03
-#define SAA7191_CTL4_VNOI_2	0x02
-#define SAA7191_CTL4_VNOI_1	0x01
-#define SAA7191_CTL4_VNOI_0	0x00
-
-/* Chrominance Gain Control Register definitions
- * - for QAM-modulated input signals, effects output amplitude
- * (SECAM gain fixed)
- * (nominal values for UV CCIR level) */
-#define SAA7191_CHCV_NTSC	0x2c
-#define SAA7191_CHCV_PAL	0x59
-
-/* Driver interface definitions */
-#define SAA7191_INPUT_COMPOSITE	0
-#define SAA7191_INPUT_SVIDEO	1
-
-#define SAA7191_NORM_PAL	1
-#define SAA7191_NORM_NTSC	2
-#define SAA7191_NORM_SECAM	3
-
-struct saa7191_status {
-	/* 0=no signal, 1=signal detected */
-	int signal;
-	/* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
-	int signal_60hz;
-	/* 0=no color detected, 1=color detected */
-	int color;
-
-	/* current SAA7191_INPUT_ */
-	int input;
-	/* current SAA7191_NORM_ */
-	int norm;
-};
-
-#define SAA7191_BANDPASS_MIN		0x00
-#define SAA7191_BANDPASS_MAX		0x03
-#define SAA7191_BANDPASS_DEFAULT	0x00
-
-#define SAA7191_BANDPASS_WEIGHT_MIN	0x00
-#define SAA7191_BANDPASS_WEIGHT_MAX	0x03
-#define SAA7191_BANDPASS_WEIGHT_DEFAULT	0x01
-
-#define SAA7191_CORING_MIN		0x00
-#define SAA7191_CORING_MAX		0x03
-#define SAA7191_CORING_DEFAULT		0x00
-
-#define SAA7191_HUE_MIN			0x00
-#define SAA7191_HUE_MAX			0xff
-#define SAA7191_HUE_DEFAULT		0x80
-
-#define SAA7191_VTRC_MIN		0x00
-#define SAA7191_VTRC_MAX		0x01
-#define SAA7191_VTRC_DEFAULT		0x00
-
-#define SAA7191_FORCE_COLOUR_MIN	0x00
-#define SAA7191_FORCE_COLOUR_MAX	0x01
-#define SAA7191_FORCE_COLOUR_DEFAULT	0x00
-
-#define SAA7191_CHROMA_GAIN_MIN		0x00
-#define SAA7191_CHROMA_GAIN_MAX		0x03
-#define SAA7191_CHROMA_GAIN_DEFAULT	0x00
-
-#define SAA7191_LUMA_DELAY_MIN		-0x04
-#define SAA7191_LUMA_DELAY_MAX		0x03
-#define SAA7191_LUMA_DELAY_DEFAULT	0x01
-
-#define SAA7191_VNR_MIN			0x00
-#define SAA7191_VNR_MAX			0x03
-#define SAA7191_VNR_DEFAULT		0x00
-
-#define SAA7191_CONTROL_BANDPASS	(V4L2_CID_PRIVATE_BASE + 0)
-#define SAA7191_CONTROL_BANDPASS_WEIGHT	(V4L2_CID_PRIVATE_BASE + 1)
-#define SAA7191_CONTROL_CORING		(V4L2_CID_PRIVATE_BASE + 2)
-#define SAA7191_CONTROL_FORCE_COLOUR	(V4L2_CID_PRIVATE_BASE + 3)
-#define SAA7191_CONTROL_CHROMA_GAIN	(V4L2_CID_PRIVATE_BASE + 4)
-#define SAA7191_CONTROL_VTRC		(V4L2_CID_PRIVATE_BASE + 5)
-#define SAA7191_CONTROL_LUMA_DELAY	(V4L2_CID_PRIVATE_BASE + 6)
-#define SAA7191_CONTROL_VNR		(V4L2_CID_PRIVATE_BASE + 7)
-
-#define	DECODER_SAA7191_GET_STATUS	_IOR('d', 195, struct saa7191_status)
-#define	DECODER_SAA7191_SET_NORM	_IOW('d', 196, int)
-
-#endif
diff --git a/drivers/staging/media/vino/vino.c b/drivers/staging/media/vino/vino.c
deleted file mode 100644
index 2c85357f774d..000000000000
--- a/drivers/staging/media/vino/vino.c
+++ /dev/null
@@ -1,4345 +0,0 @@
-/*
- * Driver for the VINO (Video In No Out) system found in SGI Indys.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
- *
- * Based on the previous version of the driver for 2.4 kernels by:
- * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
- *
- * v4l2_device/v4l2_subdev conversion by:
- * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * Note: this conversion is untested! Please contact the linux-media
- * mailinglist if you can test this, together with the test results.
- */
-
-/*
- * TODO:
- * - remove "mark pages reserved-hacks" from memory allocation code
- *   and implement fault()
- * - check decimation, calculating and reporting image size when
- *   using decimation
- * - implement read(), user mode buffers and overlay (?)
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/time.h>
-#include <linux/kmod.h>
-
-#include <linux/i2c.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/mutex.h>
-
-#include <asm/paccess.h>
-#include <asm/io.h>
-#include <asm/sgi/ip22.h>
-#include <asm/sgi/mc.h>
-
-#include "vino.h"
-#include "saa7191.h"
-#include "indycam.h"
-
-/* Uncomment the following line to get lots and lots of (mostly useless)
- * debug info.
- * Note that the debug output also slows down the driver significantly */
-// #define VINO_DEBUG
-// #define VINO_DEBUG_INT
-
-#define VINO_MODULE_VERSION "0.0.7"
-
-MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
-MODULE_VERSION(VINO_MODULE_VERSION);
-MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
-MODULE_LICENSE("GPL");
-
-#ifdef VINO_DEBUG
-#define dprintk(x...) printk("VINO: " x);
-#else
-#define dprintk(x...)
-#endif
-
-#define VINO_NO_CHANNEL			0
-#define VINO_CHANNEL_A			1
-#define VINO_CHANNEL_B			2
-
-#define VINO_PAL_WIDTH			768
-#define VINO_PAL_HEIGHT			576
-#define VINO_NTSC_WIDTH			640
-#define VINO_NTSC_HEIGHT		480
-
-#define VINO_MIN_WIDTH			32
-#define VINO_MIN_HEIGHT			32
-
-#define VINO_CLIPPING_START_ODD_D1	1
-#define VINO_CLIPPING_START_ODD_PAL	15
-#define VINO_CLIPPING_START_ODD_NTSC	12
-
-#define VINO_CLIPPING_START_EVEN_D1	2
-#define VINO_CLIPPING_START_EVEN_PAL	15
-#define VINO_CLIPPING_START_EVEN_NTSC	12
-
-#define VINO_INPUT_CHANNEL_COUNT	3
-
-/* the number is the index for vino_inputs */
-#define VINO_INPUT_NONE			-1
-#define VINO_INPUT_COMPOSITE		0
-#define VINO_INPUT_SVIDEO		1
-#define VINO_INPUT_D1			2
-
-#define VINO_PAGE_RATIO			(PAGE_SIZE / VINO_PAGE_SIZE)
-
-#define VINO_FIFO_THRESHOLD_DEFAULT	16
-
-#define VINO_FRAMEBUFFER_SIZE		((VINO_PAL_WIDTH \
-					  * VINO_PAL_HEIGHT * 4 \
-					  + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
-
-#define VINO_FRAMEBUFFER_COUNT_MAX	8
-
-#define VINO_FRAMEBUFFER_UNUSED		0
-#define VINO_FRAMEBUFFER_IN_USE		1
-#define VINO_FRAMEBUFFER_READY		2
-
-#define VINO_QUEUE_ERROR		-1
-#define VINO_QUEUE_MAGIC		0x20050125
-
-#define VINO_MEMORY_NONE		0
-#define VINO_MEMORY_MMAP		1
-#define VINO_MEMORY_USERPTR		2
-
-#define VINO_DUMMY_DESC_COUNT		4
-#define VINO_DESC_FETCH_DELAY		5	/* microseconds */
-
-#define VINO_MAX_FRAME_SKIP_COUNT	128
-
-/* the number is the index for vino_data_formats */
-#define VINO_DATA_FMT_NONE		-1
-#define VINO_DATA_FMT_GREY		0
-#define VINO_DATA_FMT_RGB332		1
-#define VINO_DATA_FMT_RGB32		2
-#define VINO_DATA_FMT_YUV		3
-
-#define VINO_DATA_FMT_COUNT		4
-
-/* the number is the index for vino_data_norms */
-#define VINO_DATA_NORM_NONE		-1
-#define VINO_DATA_NORM_NTSC		0
-#define VINO_DATA_NORM_PAL		1
-#define VINO_DATA_NORM_SECAM		2
-#define VINO_DATA_NORM_D1		3
-
-#define VINO_DATA_NORM_COUNT		4
-
-/* I2C controller flags */
-#define SGI_I2C_FORCE_IDLE		(0 << 0)
-#define SGI_I2C_NOT_IDLE		(1 << 0)
-#define SGI_I2C_WRITE			(0 << 1)
-#define SGI_I2C_READ			(1 << 1)
-#define SGI_I2C_RELEASE_BUS		(0 << 2)
-#define SGI_I2C_HOLD_BUS		(1 << 2)
-#define SGI_I2C_XFER_DONE		(0 << 4)
-#define SGI_I2C_XFER_BUSY		(1 << 4)
-#define SGI_I2C_ACK			(0 << 5)
-#define SGI_I2C_NACK			(1 << 5)
-#define SGI_I2C_BUS_OK			(0 << 7)
-#define SGI_I2C_BUS_ERR			(1 << 7)
-
-/* Internal data structure definitions */
-
-struct vino_input {
-	char *name;
-	v4l2_std_id std;
-};
-
-struct vino_clipping {
-	unsigned int left, right, top, bottom;
-};
-
-struct vino_data_format {
-	/* the description */
-	char *description;
-	/* bytes per pixel */
-	unsigned int bpp;
-	/* V4L2 fourcc code */
-	__u32 pixelformat;
-	/* V4L2 colorspace (duh!) */
-	enum v4l2_colorspace colorspace;
-};
-
-struct vino_data_norm {
-	char *description;
-	unsigned int width, height;
-	struct vino_clipping odd;
-	struct vino_clipping even;
-
-	v4l2_std_id std;
-	unsigned int fps_min, fps_max;
-	__u32 framelines;
-};
-
-struct vino_descriptor_table {
-	/* the number of PAGE_SIZE sized pages in the buffer */
-	unsigned int page_count;
-	/* virtual (kmalloc'd) pointers to the actual data
-	 * (in PAGE_SIZE chunks, used with mmap streaming) */
-	unsigned long *virtual;
-
-	/* cpu address for the VINO descriptor table
-	 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
-	unsigned long *dma_cpu;
-	/* dma address for the VINO descriptor table
-	 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
-	dma_addr_t dma;
-};
-
-struct vino_framebuffer {
-	/* identifier nubmer */
-	unsigned int id;
-	/* the length of the whole buffer */
-	unsigned int size;
-	/* the length of actual data in buffer */
-	unsigned int data_size;
-	/* the data format */
-	unsigned int data_format;
-	/* the state of buffer data */
-	unsigned int state;
-	/* is the buffer mapped in user space? */
-	unsigned int map_count;
-	/* memory offset for mmap() */
-	unsigned int offset;
-	/* frame counter */
-	unsigned int frame_counter;
-	/* timestamp (written when image capture finishes) */
-	struct timeval timestamp;
-
-	struct vino_descriptor_table desc_table;
-
-	spinlock_t state_lock;
-};
-
-struct vino_framebuffer_fifo {
-	unsigned int length;
-
-	unsigned int used;
-	unsigned int head;
-	unsigned int tail;
-
-	unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
-};
-
-struct vino_framebuffer_queue {
-	unsigned int magic;
-
-	/* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
-	unsigned int type;
-	unsigned int length;
-
-	/* data field of in and out contain index numbers for buffer */
-	struct vino_framebuffer_fifo in;
-	struct vino_framebuffer_fifo out;
-
-	struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
-
-	spinlock_t queue_lock;
-	struct mutex queue_mutex;
-	wait_queue_head_t frame_wait_queue;
-};
-
-struct vino_interrupt_data {
-	struct timeval timestamp;
-	unsigned int frame_counter;
-	unsigned int skip_count;
-	unsigned int skip;
-};
-
-struct vino_channel_settings {
-	unsigned int channel;
-
-	int input;
-	unsigned int data_format;
-	unsigned int data_norm;
-	struct vino_clipping clipping;
-	unsigned int decimation;
-	unsigned int line_size;
-	unsigned int alpha;
-	unsigned int fps;
-	unsigned int framert_reg;
-
-	unsigned int fifo_threshold;
-
-	struct vino_framebuffer_queue fb_queue;
-
-	/* number of the current field */
-	unsigned int field;
-
-	/* read in progress */
-	int reading;
-	/* streaming is active */
-	int streaming;
-	/* the driver is currently processing the queue */
-	int capturing;
-
-	struct mutex mutex;
-	spinlock_t capture_lock;
-
-	unsigned int users;
-
-	struct vino_interrupt_data int_data;
-
-	/* V4L support */
-	struct video_device *vdev;
-};
-
-struct vino_settings {
-	struct v4l2_device v4l2_dev;
-	struct vino_channel_settings a;
-	struct vino_channel_settings b;
-
-	/* the channel which owns this client:
-	 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
-	unsigned int decoder_owner;
-	struct v4l2_subdev *decoder;
-	unsigned int camera_owner;
-	struct v4l2_subdev *camera;
-
-	/* a lock for vino register access */
-	spinlock_t vino_lock;
-	/* a lock for channel input changes */
-	spinlock_t input_lock;
-
-	unsigned long dummy_page;
-	struct vino_descriptor_table dummy_desc_table;
-};
-
-/* Module parameters */
-
-/*
- * Using vino_pixel_conversion the ABGR32-format pixels supplied
- * by the VINO chip can be converted to more common formats
- * like RGBA32 (or probably RGB24 in the future). This way we
- * can give out data that can be specified correctly with
- * the V4L2-definitions.
- *
- * The pixel format is specified as RGBA32 when no conversion
- * is used.
- *
- * Note that this only affects the 32-bit bit depth.
- *
- * Use non-zero value to enable conversion.
- */
-static int vino_pixel_conversion;
-
-module_param_named(pixelconv, vino_pixel_conversion, int, 0);
-
-MODULE_PARM_DESC(pixelconv,
-		 "enable pixel conversion (non-zero value enables)");
-
-/* Internal data structures */
-
-static struct sgi_vino *vino;
-
-static struct vino_settings *vino_drvdata;
-
-#define camera_call(o, f, args...) \
-	v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
-#define decoder_call(o, f, args...) \
-	v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
-
-static const char *vino_driver_name = "vino";
-static const char *vino_driver_description = "SGI VINO";
-static const char *vino_bus_name = "GIO64 bus";
-static const char *vino_vdev_name_a = "SGI VINO Channel A";
-static const char *vino_vdev_name_b = "SGI VINO Channel B";
-
-static void vino_capture_tasklet(unsigned long channel);
-
-DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
-DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
-
-static const struct vino_input vino_inputs[] = {
-	{
-		.name		= "Composite",
-		.std		= V4L2_STD_NTSC | V4L2_STD_PAL
-		| V4L2_STD_SECAM,
-	}, {
-		.name		= "S-Video",
-		.std		= V4L2_STD_NTSC | V4L2_STD_PAL
-		| V4L2_STD_SECAM,
-	}, {
-		.name		= "D1/IndyCam",
-		.std		= V4L2_STD_NTSC,
-	}
-};
-
-static const struct vino_data_format vino_data_formats[] = {
-	{
-		.description	= "8-bit greyscale",
-		.bpp		= 1,
-		.pixelformat	= V4L2_PIX_FMT_GREY,
-		.colorspace	= V4L2_COLORSPACE_SMPTE170M,
-	}, {
-		.description	= "8-bit dithered RGB 3-3-2",
-		.bpp		= 1,
-		.pixelformat	= V4L2_PIX_FMT_RGB332,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}, {
-		.description	= "32-bit RGB",
-		.bpp		= 4,
-		.pixelformat	= V4L2_PIX_FMT_RGB32,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}, {
-		.description	= "YUV 4:2:2",
-		.bpp		= 2,
-		.pixelformat	= V4L2_PIX_FMT_YUYV, // XXX: swapped?
-		.colorspace	= V4L2_COLORSPACE_SMPTE170M,
-	}
-};
-
-static const struct vino_data_norm vino_data_norms[] = {
-	{
-		.description	= "NTSC",
-		.std		= V4L2_STD_NTSC,
-		.fps_min	= 6,
-		.fps_max	= 30,
-		.framelines	= 525,
-		.width		= VINO_NTSC_WIDTH,
-		.height		= VINO_NTSC_HEIGHT,
-		.odd		= {
-			.top	= VINO_CLIPPING_START_ODD_NTSC,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_ODD_NTSC
-			+ VINO_NTSC_HEIGHT / 2 - 1,
-			.right	= VINO_NTSC_WIDTH,
-		},
-		.even		= {
-			.top	= VINO_CLIPPING_START_EVEN_NTSC,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_EVEN_NTSC
-			+ VINO_NTSC_HEIGHT / 2 - 1,
-			.right	= VINO_NTSC_WIDTH,
-		},
-	}, {
-		.description	= "PAL",
-		.std		= V4L2_STD_PAL,
-		.fps_min	= 5,
-		.fps_max	= 25,
-		.framelines	= 625,
-		.width		= VINO_PAL_WIDTH,
-		.height		= VINO_PAL_HEIGHT,
-		.odd		= {
-			.top	= VINO_CLIPPING_START_ODD_PAL,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_ODD_PAL
-			+ VINO_PAL_HEIGHT / 2 - 1,
-			.right	= VINO_PAL_WIDTH,
-		},
-		.even		= {
-			.top	= VINO_CLIPPING_START_EVEN_PAL,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_EVEN_PAL
-			+ VINO_PAL_HEIGHT / 2 - 1,
-			.right	= VINO_PAL_WIDTH,
-		},
-	}, {
-		.description	= "SECAM",
-		.std		= V4L2_STD_SECAM,
-		.fps_min	= 5,
-		.fps_max	= 25,
-		.framelines	= 625,
-		.width		= VINO_PAL_WIDTH,
-		.height		= VINO_PAL_HEIGHT,
-		.odd		= {
-			.top	= VINO_CLIPPING_START_ODD_PAL,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_ODD_PAL
-			+ VINO_PAL_HEIGHT / 2 - 1,
-			.right	= VINO_PAL_WIDTH,
-		},
-		.even		= {
-			.top	= VINO_CLIPPING_START_EVEN_PAL,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_EVEN_PAL
-			+ VINO_PAL_HEIGHT / 2 - 1,
-			.right	= VINO_PAL_WIDTH,
-		},
-	}, {
-		.description	= "NTSC/D1",
-		.std		= V4L2_STD_NTSC,
-		.fps_min	= 6,
-		.fps_max	= 30,
-		.framelines	= 525,
-		.width		= VINO_NTSC_WIDTH,
-		.height		= VINO_NTSC_HEIGHT,
-		.odd		= {
-			.top	= VINO_CLIPPING_START_ODD_D1,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_ODD_D1
-			+ VINO_NTSC_HEIGHT / 2 - 1,
-			.right	= VINO_NTSC_WIDTH,
-		},
-		.even		= {
-			.top	= VINO_CLIPPING_START_EVEN_D1,
-			.left	= 0,
-			.bottom	= VINO_CLIPPING_START_EVEN_D1
-			+ VINO_NTSC_HEIGHT / 2 - 1,
-			.right	= VINO_NTSC_WIDTH,
-		},
-	}
-};
-
-#define VINO_INDYCAM_V4L2_CONTROL_COUNT		9
-
-struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
-	{
-		.id = V4L2_CID_AUTOGAIN,
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
-		.name = "Automatic Gain Control",
-		.minimum = 0,
-		.maximum = 1,
-		.step = 1,
-		.default_value = INDYCAM_AGC_DEFAULT,
-	}, {
-		.id = V4L2_CID_AUTO_WHITE_BALANCE,
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
-		.name = "Automatic White Balance",
-		.minimum = 0,
-		.maximum = 1,
-		.step = 1,
-		.default_value = INDYCAM_AWB_DEFAULT,
-	}, {
-		.id = V4L2_CID_GAIN,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Gain",
-		.minimum = INDYCAM_GAIN_MIN,
-		.maximum = INDYCAM_GAIN_MAX,
-		.step = 1,
-		.default_value = INDYCAM_GAIN_DEFAULT,
-	}, {
-		.id = INDYCAM_CONTROL_RED_SATURATION,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Red Saturation",
-		.minimum = INDYCAM_RED_SATURATION_MIN,
-		.maximum = INDYCAM_RED_SATURATION_MAX,
-		.step = 1,
-		.default_value = INDYCAM_RED_SATURATION_DEFAULT,
-	}, {
-		.id = INDYCAM_CONTROL_BLUE_SATURATION,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Blue Saturation",
-		.minimum = INDYCAM_BLUE_SATURATION_MIN,
-		.maximum = INDYCAM_BLUE_SATURATION_MAX,
-		.step = 1,
-		.default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
-	}, {
-		.id = V4L2_CID_RED_BALANCE,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Red Balance",
-		.minimum = INDYCAM_RED_BALANCE_MIN,
-		.maximum = INDYCAM_RED_BALANCE_MAX,
-		.step = 1,
-		.default_value = INDYCAM_RED_BALANCE_DEFAULT,
-	}, {
-		.id = V4L2_CID_BLUE_BALANCE,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Blue Balance",
-		.minimum = INDYCAM_BLUE_BALANCE_MIN,
-		.maximum = INDYCAM_BLUE_BALANCE_MAX,
-		.step = 1,
-		.default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
-	}, {
-		.id = V4L2_CID_EXPOSURE,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Shutter Control",
-		.minimum = INDYCAM_SHUTTER_MIN,
-		.maximum = INDYCAM_SHUTTER_MAX,
-		.step = 1,
-		.default_value = INDYCAM_SHUTTER_DEFAULT,
-	}, {
-		.id = V4L2_CID_GAMMA,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Gamma",
-		.minimum = INDYCAM_GAMMA_MIN,
-		.maximum = INDYCAM_GAMMA_MAX,
-		.step = 1,
-		.default_value = INDYCAM_GAMMA_DEFAULT,
-	}
-};
-
-#define VINO_SAA7191_V4L2_CONTROL_COUNT		9
-
-struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
-	{
-		.id = V4L2_CID_HUE,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Hue",
-		.minimum = SAA7191_HUE_MIN,
-		.maximum = SAA7191_HUE_MAX,
-		.step = 1,
-		.default_value = SAA7191_HUE_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_BANDPASS,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Luminance Bandpass",
-		.minimum = SAA7191_BANDPASS_MIN,
-		.maximum = SAA7191_BANDPASS_MAX,
-		.step = 1,
-		.default_value = SAA7191_BANDPASS_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_BANDPASS_WEIGHT,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Luminance Bandpass Weight",
-		.minimum = SAA7191_BANDPASS_WEIGHT_MIN,
-		.maximum = SAA7191_BANDPASS_WEIGHT_MAX,
-		.step = 1,
-		.default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_CORING,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "HF Luminance Coring",
-		.minimum = SAA7191_CORING_MIN,
-		.maximum = SAA7191_CORING_MAX,
-		.step = 1,
-		.default_value = SAA7191_CORING_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_FORCE_COLOUR,
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
-		.name = "Force Colour",
-		.minimum = SAA7191_FORCE_COLOUR_MIN,
-		.maximum = SAA7191_FORCE_COLOUR_MAX,
-		.step = 1,
-		.default_value = SAA7191_FORCE_COLOUR_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_CHROMA_GAIN,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Chrominance Gain Control",
-		.minimum = SAA7191_CHROMA_GAIN_MIN,
-		.maximum = SAA7191_CHROMA_GAIN_MAX,
-		.step = 1,
-		.default_value = SAA7191_CHROMA_GAIN_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_VTRC,
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
-		.name = "VTR Time Constant",
-		.minimum = SAA7191_VTRC_MIN,
-		.maximum = SAA7191_VTRC_MAX,
-		.step = 1,
-		.default_value = SAA7191_VTRC_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_LUMA_DELAY,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Luminance Delay Compensation",
-		.minimum = SAA7191_LUMA_DELAY_MIN,
-		.maximum = SAA7191_LUMA_DELAY_MAX,
-		.step = 1,
-		.default_value = SAA7191_LUMA_DELAY_DEFAULT,
-	}, {
-		.id = SAA7191_CONTROL_VNR,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Vertical Noise Reduction",
-		.minimum = SAA7191_VNR_MIN,
-		.maximum = SAA7191_VNR_MAX,
-		.step = 1,
-		.default_value = SAA7191_VNR_DEFAULT,
-	}
-};
-
-/* VINO framebuffer/DMA descriptor management */
-
-static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
-					       unsigned int count)
-{
-	unsigned int i;
-
-	dprintk("vino_free_buffer_with_count(): count = %d\n", count);
-
-	for (i = 0; i < count; i++) {
-		ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
-		dma_unmap_single(NULL,
-				 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
-				 PAGE_SIZE, DMA_FROM_DEVICE);
-		free_page(fb->desc_table.virtual[i]);
-	}
-
-	dma_free_coherent(NULL,
-			  VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
-			  sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
-			  fb->desc_table.dma);
-	kfree(fb->desc_table.virtual);
-
-	memset(fb, 0, sizeof(struct vino_framebuffer));
-}
-
-static void vino_free_buffer(struct vino_framebuffer *fb)
-{
-	vino_free_buffer_with_count(fb, fb->desc_table.page_count);
-}
-
-static int vino_allocate_buffer(struct vino_framebuffer *fb,
-				unsigned int size)
-{
-	unsigned int count, i, j;
-	int ret = 0;
-
-	dprintk("vino_allocate_buffer():\n");
-
-	if (size < 1)
-		return -EINVAL;
-
-	memset(fb, 0, sizeof(struct vino_framebuffer));
-
-	count = ((size / PAGE_SIZE) + 4) & ~3;
-
-	dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
-		size, count);
-
-	/* allocate memory for table with virtual (page) addresses */
-	fb->desc_table.virtual =
-		kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
-	if (!fb->desc_table.virtual)
-		return -ENOMEM;
-
-	/* allocate memory for table with dma addresses
-	 * (has space for four extra descriptors) */
-	fb->desc_table.dma_cpu =
-		dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
-				   sizeof(dma_addr_t), &fb->desc_table.dma,
-				   GFP_KERNEL | GFP_DMA);
-	if (!fb->desc_table.dma_cpu) {
-		ret = -ENOMEM;
-		goto out_free_virtual;
-	}
-
-	/* allocate pages for the buffer and acquire the according
-	 * dma addresses */
-	for (i = 0; i < count; i++) {
-		dma_addr_t dma_data_addr;
-
-		fb->desc_table.virtual[i] =
-			get_zeroed_page(GFP_KERNEL | GFP_DMA);
-		if (!fb->desc_table.virtual[i]) {
-			ret = -ENOBUFS;
-			break;
-		}
-
-		dma_data_addr =
-			dma_map_single(NULL,
-				       (void *)fb->desc_table.virtual[i],
-				       PAGE_SIZE, DMA_FROM_DEVICE);
-
-		for (j = 0; j < VINO_PAGE_RATIO; j++) {
-			fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
-				dma_data_addr + VINO_PAGE_SIZE * j;
-		}
-
-		SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
-	}
-
-	/* page_count needs to be set anyway, because the descriptor table has
-	 * been allocated according to this number */
-	fb->desc_table.page_count = count;
-
-	if (ret) {
-		/* the descriptor with index i doesn't contain
-		 * a valid address yet */
-		vino_free_buffer_with_count(fb, i);
-		return ret;
-	}
-
-	//fb->size = size;
-	fb->size = count * PAGE_SIZE;
-	fb->data_format = VINO_DATA_FMT_NONE;
-
-	/* set the dma stop-bit for the last (count+1)th descriptor */
-	fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
-	return 0;
-
- out_free_virtual:
-	kfree(fb->desc_table.virtual);
-	return ret;
-}
-
-#if 0
-/* user buffers not fully implemented yet */
-static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
-				     void *user,
-				     unsigned int size)
-{
-	unsigned int count, i, j;
-	int ret = 0;
-
-	dprintk("vino_prepare_user_buffer():\n");
-
-	if (size < 1)
-		return -EINVAL;
-
-	memset(fb, 0, sizeof(struct vino_framebuffer));
-
-	count = ((size / PAGE_SIZE)) & ~3;
-
-	dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
-		size, count);
-
-	/* allocate memory for table with virtual (page) addresses */
-	fb->desc_table.virtual = (unsigned long *)
-		kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
-	if (!fb->desc_table.virtual)
-		return -ENOMEM;
-
-	/* allocate memory for table with dma addresses
-	 * (has space for four extra descriptors) */
-	fb->desc_table.dma_cpu =
-		dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
-				   sizeof(dma_addr_t), &fb->desc_table.dma,
-				   GFP_KERNEL | GFP_DMA);
-	if (!fb->desc_table.dma_cpu) {
-		ret = -ENOMEM;
-		goto out_free_virtual;
-	}
-
-	/* allocate pages for the buffer and acquire the according
-	 * dma addresses */
-	for (i = 0; i < count; i++) {
-		dma_addr_t dma_data_addr;
-
-		fb->desc_table.virtual[i] =
-			get_zeroed_page(GFP_KERNEL | GFP_DMA);
-		if (!fb->desc_table.virtual[i]) {
-			ret = -ENOBUFS;
-			break;
-		}
-
-		dma_data_addr =
-			dma_map_single(NULL,
-				       (void *)fb->desc_table.virtual[i],
-				       PAGE_SIZE, DMA_FROM_DEVICE);
-
-		for (j = 0; j < VINO_PAGE_RATIO; j++) {
-			fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
-				dma_data_addr + VINO_PAGE_SIZE * j;
-		}
-
-		SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
-	}
-
-	/* page_count needs to be set anyway, because the descriptor table has
-	 * been allocated according to this number */
-	fb->desc_table.page_count = count;
-
-	if (ret) {
-		/* the descriptor with index i doesn't contain
-		 * a valid address yet */
-		vino_free_buffer_with_count(fb, i);
-		return ret;
-	}
-
-	//fb->size = size;
-	fb->size = count * PAGE_SIZE;
-
-	/* set the dma stop-bit for the last (count+1)th descriptor */
-	fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
-	return 0;
-
- out_free_virtual:
-	kfree(fb->desc_table.virtual);
-	return ret;
-}
-#endif
-
-static void vino_sync_buffer(struct vino_framebuffer *fb)
-{
-	int i;
-
-	dprintk("vino_sync_buffer():\n");
-
-	for (i = 0; i < fb->desc_table.page_count; i++)
-		dma_sync_single_for_cpu(NULL,
-					fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
-					PAGE_SIZE, DMA_FROM_DEVICE);
-}
-
-/* Framebuffer fifo functions (need to be locked externally) */
-
-static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
-			   unsigned int length)
-{
-	f->length = 0;
-	f->used = 0;
-	f->head = 0;
-	f->tail = 0;
-
-	if (length > VINO_FRAMEBUFFER_COUNT_MAX)
-		length = VINO_FRAMEBUFFER_COUNT_MAX;
-
-	f->length = length;
-}
-
-/* returns true/false */
-static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
-				   unsigned int id)
-{
-	unsigned int i;
-
-	for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
-		if (f->data[i] == id)
-			return 1;
-	}
-
-	return 0;
-}
-
-#if 0
-/* returns true/false */
-static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
-{
-	return (f->used == f->length);
-}
-#endif
-
-static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
-{
-	return f->used;
-}
-
-static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
-{
-	if (id >= f->length) {
-		return VINO_QUEUE_ERROR;
-	}
-
-	if (vino_fifo_has_id(f, id)) {
-		return VINO_QUEUE_ERROR;
-	}
-
-	if (f->used < f->length) {
-		f->data[f->tail] = id;
-		f->tail = (f->tail + 1) % f->length;
-		f->used++;
-	} else {
-		return VINO_QUEUE_ERROR;
-	}
-
-	return 0;
-}
-
-static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
-{
-	if (f->used > 0) {
-		*id = f->data[f->head];
-	} else {
-		return VINO_QUEUE_ERROR;
-	}
-
-	return 0;
-}
-
-static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
-{
-	if (f->used > 0) {
-		*id = f->data[f->head];
-		f->head = (f->head + 1) % f->length;
-		f->used--;
-	} else {
-		return VINO_QUEUE_ERROR;
-	}
-
-	return 0;
-}
-
-/* Framebuffer queue functions */
-
-/* execute with queue_lock locked */
-static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
-				       unsigned int length)
-{
-	unsigned int i;
-
-	q->length = 0;
-	memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
-	memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
-	for (i = 0; i < length; i++) {
-		dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
-			i);
-		vino_free_buffer(q->buffer[i]);
-		kfree(q->buffer[i]);
-	}
-
-	q->type = VINO_MEMORY_NONE;
-	q->magic = 0;
-}
-
-static void vino_queue_free(struct vino_framebuffer_queue *q)
-{
-	dprintk("vino_queue_free():\n");
-
-	if (q->magic != VINO_QUEUE_MAGIC)
-		return;
-	if (q->type != VINO_MEMORY_MMAP)
-		return;
-
-	mutex_lock(&q->queue_mutex);
-
-	vino_queue_free_with_count(q, q->length);
-
-	mutex_unlock(&q->queue_mutex);
-}
-
-static int vino_queue_init(struct vino_framebuffer_queue *q,
-			   unsigned int *length)
-{
-	unsigned int i;
-	int ret = 0;
-
-	dprintk("vino_queue_init(): length = %d\n", *length);
-
-	if (q->magic == VINO_QUEUE_MAGIC) {
-		dprintk("vino_queue_init(): queue already initialized!\n");
-		return -EINVAL;
-	}
-
-	if (q->type != VINO_MEMORY_NONE) {
-		dprintk("vino_queue_init(): queue already initialized!\n");
-		return -EINVAL;
-	}
-
-	if (*length < 1)
-		return -EINVAL;
-
-	mutex_lock(&q->queue_mutex);
-
-	if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
-		*length = VINO_FRAMEBUFFER_COUNT_MAX;
-
-	q->length = 0;
-
-	for (i = 0; i < *length; i++) {
-		dprintk("vino_queue_init(): allocating buffer %d\n", i);
-		q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
-				       GFP_KERNEL);
-		if (!q->buffer[i]) {
-			dprintk("vino_queue_init(): kmalloc() failed\n");
-			ret = -ENOMEM;
-			break;
-		}
-
-		ret = vino_allocate_buffer(q->buffer[i],
-					   VINO_FRAMEBUFFER_SIZE);
-		if (ret) {
-			kfree(q->buffer[i]);
-			dprintk("vino_queue_init(): "
-				"vino_allocate_buffer() failed\n");
-			break;
-		}
-
-		q->buffer[i]->id = i;
-		if (i > 0) {
-			q->buffer[i]->offset = q->buffer[i - 1]->offset +
-				q->buffer[i - 1]->size;
-		} else {
-			q->buffer[i]->offset = 0;
-		}
-
-		spin_lock_init(&q->buffer[i]->state_lock);
-
-		dprintk("vino_queue_init(): buffer = %d, offset = %d, "
-			"size = %d\n", i, q->buffer[i]->offset,
-			q->buffer[i]->size);
-	}
-
-	if (ret) {
-		vino_queue_free_with_count(q, i);
-		*length = 0;
-	} else {
-		q->length = *length;
-		vino_fifo_init(&q->in, q->length);
-		vino_fifo_init(&q->out, q->length);
-		q->type = VINO_MEMORY_MMAP;
-		q->magic = VINO_QUEUE_MAGIC;
-	}
-
-	mutex_unlock(&q->queue_mutex);
-
-	return ret;
-}
-
-static struct vino_framebuffer *vino_queue_add(struct
-					       vino_framebuffer_queue *q,
-					       unsigned int id)
-{
-	struct vino_framebuffer *ret = NULL;
-	unsigned int total;
-	unsigned long flags;
-
-	dprintk("vino_queue_add(): id = %d\n", id);
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	if (id >= q->length)
-		goto out;
-
-	/* not needed?: if (vino_fifo_full(&q->out)) {
-		goto out;
-		}*/
-	/* check that outgoing queue isn't already full
-	 * (or that it won't become full) */
-	total = vino_fifo_get_used(&q->in) +
-		vino_fifo_get_used(&q->out);
-	if (total >= q->length)
-		goto out;
-
-	if (vino_fifo_enqueue(&q->in, id))
-		goto out;
-
-	ret = q->buffer[id];
-
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-static struct vino_framebuffer *vino_queue_transfer(struct
-						    vino_framebuffer_queue *q)
-{
-	struct vino_framebuffer *ret = NULL;
-	struct vino_framebuffer *fb;
-	int id;
-	unsigned long flags;
-
-	dprintk("vino_queue_transfer():\n");
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	// now this actually removes an entry from the incoming queue
-	if (vino_fifo_dequeue(&q->in, &id)) {
-		goto out;
-	}
-
-	dprintk("vino_queue_transfer(): id = %d\n", id);
-	fb = q->buffer[id];
-
-	// we have already checked that the outgoing queue is not full, but...
-	if (vino_fifo_enqueue(&q->out, id)) {
-		printk(KERN_ERR "vino_queue_transfer(): "
-		       "outgoing queue is full, this shouldn't happen!\n");
-		goto out;
-	}
-
-	ret = fb;
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-/* returns true/false */
-static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
-					unsigned int id)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	ret = vino_fifo_has_id(&q->in, id);
-
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-/* returns true/false */
-static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
-					unsigned int id)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	ret = vino_fifo_has_id(&q->out, id);
-
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
-				   unsigned int *used)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return VINO_QUEUE_ERROR;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0) {
-		ret = VINO_QUEUE_ERROR;
-		goto out;
-	}
-
-	*used = vino_fifo_get_used(&q->in);
-
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
-				   unsigned int *used)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return VINO_QUEUE_ERROR;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0) {
-		ret = VINO_QUEUE_ERROR;
-		goto out;
-	}
-
-	*used = vino_fifo_get_used(&q->out);
-
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-#if 0
-static int vino_queue_get_total(struct vino_framebuffer_queue *q,
-				unsigned int *total)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return VINO_QUEUE_ERROR;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0) {
-		ret = VINO_QUEUE_ERROR;
-		goto out;
-	}
-
-	*total = vino_fifo_get_used(&q->in) +
-		vino_fifo_get_used(&q->out);
-
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-#endif
-
-static struct vino_framebuffer *vino_queue_peek(struct
-						vino_framebuffer_queue *q,
-						unsigned int *id)
-{
-	struct vino_framebuffer *ret = NULL;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	if (vino_fifo_peek(&q->in, id)) {
-		goto out;
-	}
-
-	ret = q->buffer[*id];
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-static struct vino_framebuffer *vino_queue_remove(struct
-						  vino_framebuffer_queue *q,
-						  unsigned int *id)
-{
-	struct vino_framebuffer *ret = NULL;
-	unsigned long flags;
-	dprintk("vino_queue_remove():\n");
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	if (vino_fifo_dequeue(&q->out, id)) {
-		goto out;
-	}
-
-	dprintk("vino_queue_remove(): id = %d\n", *id);
-	ret = q->buffer[*id];
-out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-static struct
-vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
-					unsigned int id)
-{
-	struct vino_framebuffer *ret = NULL;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-
-	if (q->length == 0)
-		goto out;
-
-	if (id >= q->length)
-		goto out;
-
-	ret = q->buffer[id];
- out:
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
-{
-	unsigned int length = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return length;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-	length = q->length;
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return length;
-}
-
-static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
-{
-	unsigned int i;
-	int ret = 0;
-	unsigned long flags;
-
-	if (q->magic != VINO_QUEUE_MAGIC) {
-		return ret;
-	}
-
-	spin_lock_irqsave(&q->queue_lock, flags);
-	for (i = 0; i < q->length; i++) {
-		if (q->buffer[i]->map_count > 0) {
-			ret = 1;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&q->queue_lock, flags);
-
-	return ret;
-}
-
-/* VINO functions */
-
-/* execute with input_lock locked */
-static void vino_update_line_size(struct vino_channel_settings *vcs)
-{
-	unsigned int w = vcs->clipping.right - vcs->clipping.left;
-	unsigned int d = vcs->decimation;
-	unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
-	unsigned int lsize;
-
-	dprintk("update_line_size(): before: w = %d, d = %d, "
-		"line_size = %d\n", w, d, vcs->line_size);
-
-	/* line size must be multiple of 8 bytes */
-	lsize = (bpp * (w / d)) & ~7;
-	w = (lsize / bpp) * d;
-
-	vcs->clipping.right = vcs->clipping.left + w;
-	vcs->line_size = lsize;
-
-	dprintk("update_line_size(): after: w = %d, d = %d, "
-		"line_size = %d\n", w, d, vcs->line_size);
-}
-
-/* execute with input_lock locked */
-static void vino_set_clipping(struct vino_channel_settings *vcs,
-			      unsigned int x, unsigned int y,
-			      unsigned int w, unsigned int h)
-{
-	unsigned int maxwidth, maxheight;
-	unsigned int d;
-
-	maxwidth = vino_data_norms[vcs->data_norm].width;
-	maxheight = vino_data_norms[vcs->data_norm].height;
-	d = vcs->decimation;
-
-	y &= ~1;	/* odd/even fields */
-
-	if (x > maxwidth) {
-		x = 0;
-	}
-	if (y > maxheight) {
-		y = 0;
-	}
-
-	if (((w / d) < VINO_MIN_WIDTH)
-	    || ((h / d) < VINO_MIN_HEIGHT)) {
-		w = VINO_MIN_WIDTH * d;
-		h = VINO_MIN_HEIGHT * d;
-	}
-
-	if ((x + w) > maxwidth) {
-		w = maxwidth - x;
-		if ((w / d) < VINO_MIN_WIDTH)
-			x = maxwidth - VINO_MIN_WIDTH * d;
-	}
-	if ((y + h) > maxheight) {
-		h = maxheight - y;
-		if ((h / d) < VINO_MIN_HEIGHT)
-			y = maxheight - VINO_MIN_HEIGHT * d;
-	}
-
-	vcs->clipping.left = x;
-	vcs->clipping.top = y;
-	vcs->clipping.right = x + w;
-	vcs->clipping.bottom = y + h;
-
-	vino_update_line_size(vcs);
-
-	dprintk("clipping %d, %d, %d, %d / %d - %d\n",
-		vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
-		vcs->clipping.bottom, vcs->decimation, vcs->line_size);
-}
-
-/* execute with input_lock locked */
-static inline void vino_set_default_clipping(struct vino_channel_settings *vcs)
-{
-	vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
-			  vino_data_norms[vcs->data_norm].height);
-}
-
-/* execute with input_lock locked */
-static void vino_set_scaling(struct vino_channel_settings *vcs,
-			     unsigned int w, unsigned int h)
-{
-	unsigned int x, y, curw, curh, d;
-
-	x = vcs->clipping.left;
-	y = vcs->clipping.top;
-	curw = vcs->clipping.right - vcs->clipping.left;
-	curh = vcs->clipping.bottom - vcs->clipping.top;
-
-	d = max(curw / w, curh / h);
-
-	dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
-		w, h, curw, curh, d);
-
-	if (d < 1) {
-		d = 1;
-	} else if (d > 8) {
-		d = 8;
-	}
-
-	vcs->decimation = d;
-	vino_set_clipping(vcs, x, y, w * d, h * d);
-
-	dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
-		vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
-		vcs->decimation, vcs->line_size);
-}
-
-/* execute with input_lock locked */
-static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
-{
-	vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
-			 vcs->clipping.bottom - vcs->clipping.top);
-}
-
-/* execute with input_lock locked */
-static void vino_set_framerate(struct vino_channel_settings *vcs,
-			       unsigned int fps)
-{
-	unsigned int mask;
-
-	switch (vcs->data_norm) {
-	case VINO_DATA_NORM_NTSC:
-	case VINO_DATA_NORM_D1:
-		fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
-
-		if (fps < vino_data_norms[vcs->data_norm].fps_min)
-			fps = vino_data_norms[vcs->data_norm].fps_min;
-		if (fps > vino_data_norms[vcs->data_norm].fps_max)
-			fps = vino_data_norms[vcs->data_norm].fps_max;
-
-		switch (fps) {
-		case 6:
-			mask = 0x003;
-			break;
-		case 12:
-			mask = 0x0c3;
-			break;
-		case 18:
-			mask = 0x333;
-			break;
-		case 24:
-			mask = 0x3ff;
-			break;
-		case 30:
-			mask = 0xfff;
-			break;
-		default:
-			mask = VINO_FRAMERT_FULL;
-		}
-		vcs->framert_reg = VINO_FRAMERT_RT(mask);
-		break;
-	case VINO_DATA_NORM_PAL:
-	case VINO_DATA_NORM_SECAM:
-		fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
-
-		if (fps < vino_data_norms[vcs->data_norm].fps_min)
-			fps = vino_data_norms[vcs->data_norm].fps_min;
-		if (fps > vino_data_norms[vcs->data_norm].fps_max)
-			fps = vino_data_norms[vcs->data_norm].fps_max;
-
-		switch (fps) {
-		case 5:
-			mask = 0x003;
-			break;
-		case 10:
-			mask = 0x0c3;
-			break;
-		case 15:
-			mask = 0x333;
-			break;
-		case 20:
-			mask = 0x0ff;
-			break;
-		case 25:
-			mask = 0x3ff;
-			break;
-		default:
-			mask = VINO_FRAMERT_FULL;
-		}
-		vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
-		break;
-	}
-
-	vcs->fps = fps;
-}
-
-/* execute with input_lock locked */
-static inline void vino_set_default_framerate(struct
-					      vino_channel_settings *vcs)
-{
-	vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
-}
-
-/* VINO I2C bus functions */
-
-struct i2c_algo_sgi_data {
-	void *data;	/* private data for lowlevel routines */
-	unsigned (*getctrl)(void *data);
-	void (*setctrl)(void *data, unsigned val);
-	unsigned (*rdata)(void *data);
-	void (*wdata)(void *data, unsigned val);
-
-	int xfer_timeout;
-	int ack_timeout;
-};
-
-static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
-{
-	int i;
-
-	for (i = 0; i < adap->xfer_timeout; i++) {
-		if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
-			return 0;
-		udelay(1);
-	}
-
-	return -ETIMEDOUT;
-}
-
-static int wait_ack(struct i2c_algo_sgi_data *adap)
-{
-	int i;
-
-	if (wait_xfer_done(adap))
-		return -ETIMEDOUT;
-	for (i = 0; i < adap->ack_timeout; i++) {
-		if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
-			return 0;
-		udelay(1);
-	}
-
-	return -ETIMEDOUT;
-}
-
-static int force_idle(struct i2c_algo_sgi_data *adap)
-{
-	int i;
-
-	adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
-	for (i = 0; i < adap->xfer_timeout; i++) {
-		if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
-			goto out;
-		udelay(1);
-	}
-	return -ETIMEDOUT;
-out:
-	if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
-		return -EIO;
-	return 0;
-}
-
-static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
-		      int rd)
-{
-	if (rd)
-		adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
-	/* Check if bus is idle, eventually force it to do so */
-	if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
-		if (force_idle(adap))
-			return -EIO;
-	/* Write out the i2c chip address and specify operation */
-	adap->setctrl(adap->data,
-		      SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
-	if (rd)
-		addr |= 1;
-	adap->wdata(adap->data, addr);
-	if (wait_ack(adap))
-		return -EIO;
-	return 0;
-}
-
-static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
-		    unsigned int len)
-{
-	int i;
-
-	adap->setctrl(adap->data,
-		      SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
-	for (i = 0; i < len; i++) {
-		if (wait_xfer_done(adap))
-			return -EIO;
-		buf[i] = adap->rdata(adap->data);
-	}
-	adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
-
-	return 0;
-
-}
-
-static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
-		     unsigned int len)
-{
-	int i;
-
-	/* We are already in write state */
-	for (i = 0; i < len; i++) {
-		adap->wdata(adap->data, buf[i]);
-		if (wait_ack(adap))
-			return -EIO;
-	}
-	return 0;
-}
-
-static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
-		    int num)
-{
-	struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
-	struct i2c_msg *p;
-	int i, err = 0;
-
-	for (i = 0; !err && i < num; i++) {
-		p = &msgs[i];
-		err = do_address(adap, p->addr, p->flags & I2C_M_RD);
-		if (err || !p->len)
-			continue;
-		if (p->flags & I2C_M_RD)
-			err = i2c_read(adap, p->buf, p->len);
-		else
-			err = i2c_write(adap, p->buf, p->len);
-	}
-
-	return (err < 0) ? err : i;
-}
-
-static u32 sgi_func(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm sgi_algo = {
-	.master_xfer	= sgi_xfer,
-	.functionality	= sgi_func,
-};
-
-static unsigned i2c_vino_getctrl(void *data)
-{
-	return vino->i2c_control;
-}
-
-static void i2c_vino_setctrl(void *data, unsigned val)
-{
-	vino->i2c_control = val;
-}
-
-static unsigned i2c_vino_rdata(void *data)
-{
-	return vino->i2c_data;
-}
-
-static void i2c_vino_wdata(void *data, unsigned val)
-{
-	vino->i2c_data = val;
-}
-
-static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
-	.getctrl = &i2c_vino_getctrl,
-	.setctrl = &i2c_vino_setctrl,
-	.rdata   = &i2c_vino_rdata,
-	.wdata   = &i2c_vino_wdata,
-	.xfer_timeout = 200,
-	.ack_timeout  = 1000,
-};
-
-static struct i2c_adapter vino_i2c_adapter = {
-	.name			= "VINO I2C bus",
-	.algo			= &sgi_algo,
-	.algo_data		= &i2c_sgi_vino_data,
-	.owner 			= THIS_MODULE,
-};
-
-/*
- * Prepare VINO for DMA transfer...
- * (execute only with vino_lock and input_lock locked)
- */
-static int vino_dma_setup(struct vino_channel_settings *vcs,
-			  struct vino_framebuffer *fb)
-{
-	u32 ctrl, intr;
-	struct sgi_vino_channel *ch;
-	const struct vino_data_norm *norm;
-
-	dprintk("vino_dma_setup():\n");
-
-	vcs->field = 0;
-	fb->frame_counter = 0;
-
-	ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
-	norm = &vino_data_norms[vcs->data_norm];
-
-	ch->page_index = 0;
-	ch->line_count = 0;
-
-	/* VINO line size register is set 8 bytes less than actual */
-	ch->line_size = vcs->line_size - 8;
-
-	/* let VINO know where to transfer data */
-	ch->start_desc_tbl = fb->desc_table.dma;
-	ch->next_4_desc = fb->desc_table.dma;
-
-	/* give vino time to fetch the first four descriptors, 5 usec
-	 * should be more than enough time */
-	udelay(VINO_DESC_FETCH_DELAY);
-
-	dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
-		ch->start_desc_tbl, ch->next_4_desc);
-
-	/* set the alpha register */
-	ch->alpha = vcs->alpha;
-
-	/* set clipping registers */
-	ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
-		VINO_CLIP_EVEN(norm->even.top +
-			       vcs->clipping.top / 2) |
-		VINO_CLIP_X(vcs->clipping.left);
-	ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
-				     vcs->clipping.bottom / 2 - 1) |
-		VINO_CLIP_EVEN(norm->even.top +
-			       vcs->clipping.bottom / 2 - 1) |
-		VINO_CLIP_X(vcs->clipping.right);
-
-	/* set the size of actual content in the buffer (DECIMATION !) */
-	fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
-			 vcs->decimation) *
-		((vcs->clipping.bottom - vcs->clipping.top) /
-		 vcs->decimation) *
-		vino_data_formats[vcs->data_format].bpp;
-
-	ch->frame_rate = vcs->framert_reg;
-
-	ctrl = vino->control;
-	intr = vino->intr_status;
-
-	if (vcs->channel == VINO_CHANNEL_A) {
-		/* All interrupt conditions for this channel was cleared
-		 * so clear the interrupt status register and enable
-		 * interrupts */
-		intr &=	~VINO_INTSTAT_A;
-		ctrl |= VINO_CTRL_A_INT;
-
-		/* enable synchronization */
-		ctrl |= VINO_CTRL_A_SYNC_ENBL;
-
-		/* enable frame assembly */
-		ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
-
-		/* set decimation used */
-		if (vcs->decimation < 2)
-			ctrl &= ~VINO_CTRL_A_DEC_ENBL;
-		else {
-			ctrl |= VINO_CTRL_A_DEC_ENBL;
-			ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
-			ctrl |= (vcs->decimation - 1) <<
-				VINO_CTRL_A_DEC_SCALE_SHIFT;
-		}
-
-		/* select input interface */
-		if (vcs->input == VINO_INPUT_D1)
-			ctrl |= VINO_CTRL_A_SELECT;
-		else
-			ctrl &= ~VINO_CTRL_A_SELECT;
-
-		/* palette */
-		ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
-			  VINO_CTRL_A_DITHER);
-	} else {
-		intr &= ~VINO_INTSTAT_B;
-		ctrl |= VINO_CTRL_B_INT;
-
-		ctrl |= VINO_CTRL_B_SYNC_ENBL;
-		ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
-
-		if (vcs->decimation < 2)
-			ctrl &= ~VINO_CTRL_B_DEC_ENBL;
-		else {
-			ctrl |= VINO_CTRL_B_DEC_ENBL;
-			ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
-			ctrl |= (vcs->decimation - 1) <<
-				VINO_CTRL_B_DEC_SCALE_SHIFT;
-
-		}
-		if (vcs->input == VINO_INPUT_D1)
-			ctrl |= VINO_CTRL_B_SELECT;
-		else
-			ctrl &= ~VINO_CTRL_B_SELECT;
-
-		ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
-			  VINO_CTRL_B_DITHER);
-	}
-
-	/* set palette */
-	fb->data_format = vcs->data_format;
-
-	switch (vcs->data_format) {
-		case VINO_DATA_FMT_GREY:
-			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
-				VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
-			break;
-		case VINO_DATA_FMT_RGB32:
-			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
-				VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
-			break;
-		case VINO_DATA_FMT_YUV:
-			/* nothing needs to be done */
-			break;
-		case VINO_DATA_FMT_RGB332:
-			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
-				VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
-				VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
-			break;
-	}
-
-	vino->intr_status = intr;
-	vino->control = ctrl;
-
-	return 0;
-}
-
-/* (execute only with vino_lock locked) */
-static inline void vino_dma_start(struct vino_channel_settings *vcs)
-{
-	u32 ctrl = vino->control;
-
-	dprintk("vino_dma_start():\n");
-	ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
-		VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
-	vino->control = ctrl;
-}
-
-/* (execute only with vino_lock locked) */
-static inline void vino_dma_stop(struct vino_channel_settings *vcs)
-{
-	u32 ctrl = vino->control;
-
-	ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
-		~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
-	ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
-		~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
-	vino->control = ctrl;
-	dprintk("vino_dma_stop():\n");
-}
-
-/*
- * Load dummy page to descriptor registers. This prevents generating of
- * spurious interrupts. (execute only with vino_lock locked)
- */
-static void vino_clear_interrupt(struct vino_channel_settings *vcs)
-{
-	struct sgi_vino_channel *ch;
-
-	ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
-
-	ch->page_index = 0;
-	ch->line_count = 0;
-
-	ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
-	ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
-
-	udelay(VINO_DESC_FETCH_DELAY);
-	dprintk("channel %c clear interrupt condition\n",
-	       (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
-}
-
-static int vino_capture(struct vino_channel_settings *vcs,
-			struct vino_framebuffer *fb)
-{
-	int err = 0;
-	unsigned long flags, flags2;
-
-	spin_lock_irqsave(&fb->state_lock, flags);
-
-	if (fb->state == VINO_FRAMEBUFFER_IN_USE)
-		err = -EBUSY;
-	fb->state = VINO_FRAMEBUFFER_IN_USE;
-
-	spin_unlock_irqrestore(&fb->state_lock, flags);
-
-	if (err)
-		return err;
-
-	spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
-
-	vino_dma_setup(vcs, fb);
-	vino_dma_start(vcs);
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
-	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
-
-	return err;
-}
-
-static
-struct vino_framebuffer *vino_capture_enqueue(struct
-					      vino_channel_settings *vcs,
-					      unsigned int index)
-{
-	struct vino_framebuffer *fb;
-	unsigned long flags;
-
-	dprintk("vino_capture_enqueue():\n");
-
-	spin_lock_irqsave(&vcs->capture_lock, flags);
-
-	fb = vino_queue_add(&vcs->fb_queue, index);
-	if (fb == NULL) {
-		dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
-			"queue full?\n");
-		goto out;
-	}
-out:
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-
-	return fb;
-}
-
-static int vino_capture_next(struct vino_channel_settings *vcs, int start)
-{
-	struct vino_framebuffer *fb;
-	unsigned int incoming, id;
-	int err = 0;
-	unsigned long flags;
-
-	dprintk("vino_capture_next():\n");
-
-	spin_lock_irqsave(&vcs->capture_lock, flags);
-
-	if (start) {
-		/* start capture only if capture isn't in progress already */
-		if (vcs->capturing) {
-			spin_unlock_irqrestore(&vcs->capture_lock, flags);
-			return 0;
-		}
-
-	} else {
-		/* capture next frame:
-		 * stop capture if capturing is not set */
-		if (!vcs->capturing) {
-			spin_unlock_irqrestore(&vcs->capture_lock, flags);
-			return 0;
-		}
-	}
-
-	err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
-	if (err) {
-		dprintk("vino_capture_next(): vino_queue_get_incoming() "
-			"failed\n");
-		err = -EINVAL;
-		goto out;
-	}
-	if (incoming == 0) {
-		dprintk("vino_capture_next(): no buffers available\n");
-		goto out;
-	}
-
-	fb = vino_queue_peek(&vcs->fb_queue, &id);
-	if (fb == NULL) {
-		dprintk("vino_capture_next(): vino_queue_peek() failed\n");
-		err = -EINVAL;
-		goto out;
-	}
-
-	if (start) {
-		vcs->capturing = 1;
-	}
-
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-
-	err = vino_capture(vcs, fb);
-
-	return err;
-
-out:
-	vcs->capturing = 0;
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-
-	return err;
-}
-
-static inline int vino_is_capturing(struct vino_channel_settings *vcs)
-{
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vcs->capture_lock, flags);
-
-	ret = vcs->capturing;
-
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-
-	return ret;
-}
-
-/* waits until a frame is captured */
-static int vino_wait_for_frame(struct vino_channel_settings *vcs)
-{
-	wait_queue_t wait;
-	int err = 0;
-
-	dprintk("vino_wait_for_frame():\n");
-
-	init_waitqueue_entry(&wait, current);
-	/* add ourselves into wait queue */
-	add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
-
-	/* to ensure that schedule_timeout will return immediately
-	 * if VINO interrupt was triggered meanwhile */
-	schedule_timeout_interruptible(msecs_to_jiffies(100));
-
-	if (signal_pending(current))
-		err = -EINTR;
-
-	remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
-
-	dprintk("vino_wait_for_frame(): waiting for frame %s\n",
-		err ? "failed" : "ok");
-
-	return err;
-}
-
-/* the function assumes that PAGE_SIZE % 4 == 0 */
-static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
-	unsigned char *pageptr;
-	unsigned int page, i;
-	unsigned char a;
-
-	for (page = 0; page < fb->desc_table.page_count; page++) {
-		pageptr = (unsigned char *)fb->desc_table.virtual[page];
-
-		for (i = 0; i < PAGE_SIZE; i += 4) {
-			a = pageptr[0];
-			pageptr[0] = pageptr[3];
-			pageptr[1] = pageptr[2];
-			pageptr[2] = pageptr[1];
-			pageptr[3] = a;
-			pageptr += 4;
-		}
-	}
-}
-
-/* checks if the buffer is in correct state and syncs data */
-static int vino_check_buffer(struct vino_channel_settings *vcs,
-			     struct vino_framebuffer *fb)
-{
-	int err = 0;
-	unsigned long flags;
-
-	dprintk("vino_check_buffer():\n");
-
-	spin_lock_irqsave(&fb->state_lock, flags);
-	switch (fb->state) {
-	case VINO_FRAMEBUFFER_IN_USE:
-		err = -EIO;
-		break;
-	case VINO_FRAMEBUFFER_READY:
-		vino_sync_buffer(fb);
-		fb->state = VINO_FRAMEBUFFER_UNUSED;
-		break;
-	default:
-		err = -EINVAL;
-	}
-	spin_unlock_irqrestore(&fb->state_lock, flags);
-
-	if (!err) {
-		if (vino_pixel_conversion
-		    && (fb->data_format == VINO_DATA_FMT_RGB32)) {
-			vino_convert_to_rgba(fb);
-		}
-	} else if (err && (err != -EINVAL)) {
-		dprintk("vino_check_buffer(): buffer not ready\n");
-
-		spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
-		vino_dma_stop(vcs);
-		vino_clear_interrupt(vcs);
-		spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
-	}
-
-	return err;
-}
-
-/* forcefully terminates capture */
-static void vino_capture_stop(struct vino_channel_settings *vcs)
-{
-	unsigned int incoming = 0, outgoing = 0, id;
-	unsigned long flags, flags2;
-
-	dprintk("vino_capture_stop():\n");
-
-	spin_lock_irqsave(&vcs->capture_lock, flags);
-
-	/* unset capturing to stop queue processing */
-	vcs->capturing = 0;
-
-	spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
-
-	vino_dma_stop(vcs);
-	vino_clear_interrupt(vcs);
-
-	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
-
-	/* remove all items from the queue */
-	if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
-		dprintk("vino_capture_stop(): "
-			"vino_queue_get_incoming() failed\n");
-		goto out;
-	}
-	while (incoming > 0) {
-		vino_queue_transfer(&vcs->fb_queue);
-
-		if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
-			dprintk("vino_capture_stop(): "
-				"vino_queue_get_incoming() failed\n");
-			goto out;
-		}
-	}
-
-	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
-		dprintk("vino_capture_stop(): "
-			"vino_queue_get_outgoing() failed\n");
-		goto out;
-	}
-	while (outgoing > 0) {
-		vino_queue_remove(&vcs->fb_queue, &id);
-
-		if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
-			dprintk("vino_capture_stop(): "
-				"vino_queue_get_outgoing() failed\n");
-			goto out;
-		}
-	}
-
-out:
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-}
-
-#if 0
-static int vino_capture_failed(struct vino_channel_settings *vcs)
-{
-	struct vino_framebuffer *fb;
-	unsigned long flags;
-	unsigned int i;
-	int ret;
-
-	dprintk("vino_capture_failed():\n");
-
-	spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
-
-	vino_dma_stop(vcs);
-	vino_clear_interrupt(vcs);
-
-	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
-
-	ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
-	if (ret == VINO_QUEUE_ERROR) {
-		dprintk("vino_queue_get_incoming() failed\n");
-		return -EINVAL;
-	}
-	if (i == 0) {
-		/* no buffers to process */
-		return 0;
-	}
-
-	fb = vino_queue_peek(&vcs->fb_queue, &i);
-	if (fb == NULL) {
-		dprintk("vino_queue_peek() failed\n");
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&fb->state_lock, flags);
-	if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
-		fb->state = VINO_FRAMEBUFFER_UNUSED;
-		vino_queue_transfer(&vcs->fb_queue);
-		vino_queue_remove(&vcs->fb_queue, &i);
-		/* we should actually discard the newest frame,
-		 * but who cares ... */
-	}
-	spin_unlock_irqrestore(&fb->state_lock, flags);
-
-	return 0;
-}
-#endif
-
-static void vino_skip_frame(struct vino_channel_settings *vcs)
-{
-	struct vino_framebuffer *fb;
-	unsigned long flags;
-	unsigned int id;
-
-	spin_lock_irqsave(&vcs->capture_lock, flags);
-	fb = vino_queue_peek(&vcs->fb_queue, &id);
-	if (!fb) {
-		spin_unlock_irqrestore(&vcs->capture_lock, flags);
-		dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
-		return;
-	}
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-
-	spin_lock_irqsave(&fb->state_lock, flags);
-	fb->state = VINO_FRAMEBUFFER_UNUSED;
-	spin_unlock_irqrestore(&fb->state_lock, flags);
-
-	vino_capture_next(vcs, 0);
-}
-
-static void vino_frame_done(struct vino_channel_settings *vcs)
-{
-	struct vino_framebuffer *fb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vcs->capture_lock, flags);
-	fb = vino_queue_transfer(&vcs->fb_queue);
-	if (!fb) {
-		spin_unlock_irqrestore(&vcs->capture_lock, flags);
-		dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
-		return;
-	}
-	spin_unlock_irqrestore(&vcs->capture_lock, flags);
-
-	fb->frame_counter = vcs->int_data.frame_counter;
-	memcpy(&fb->timestamp, &vcs->int_data.timestamp,
-	       sizeof(struct timeval));
-
-	spin_lock_irqsave(&fb->state_lock, flags);
-	if (fb->state == VINO_FRAMEBUFFER_IN_USE)
-		fb->state = VINO_FRAMEBUFFER_READY;
-	spin_unlock_irqrestore(&fb->state_lock, flags);
-
-	wake_up(&vcs->fb_queue.frame_wait_queue);
-
-	vino_capture_next(vcs, 0);
-}
-
-static void vino_capture_tasklet(unsigned long channel) {
-	struct vino_channel_settings *vcs;
-
-	vcs = (channel == VINO_CHANNEL_A)
-		? &vino_drvdata->a : &vino_drvdata->b;
-
-	if (vcs->int_data.skip)
-		vcs->int_data.skip_count++;
-
-	if (vcs->int_data.skip && (vcs->int_data.skip_count
-				   <= VINO_MAX_FRAME_SKIP_COUNT)) {
-		vino_skip_frame(vcs);
-	} else {
-		vcs->int_data.skip_count = 0;
-		vino_frame_done(vcs);
-	}
-}
-
-static irqreturn_t vino_interrupt(int irq, void *dev_id)
-{
-	u32 ctrl, intr;
-	unsigned int fc_a, fc_b;
-	int handled_a = 0, skip_a = 0, done_a = 0;
-	int handled_b = 0, skip_b = 0, done_b = 0;
-
-#ifdef VINO_DEBUG_INT
-	int loop = 0;
-	unsigned int line_count = vino->a.line_count,
-		page_index = vino->a.page_index,
-		field_counter = vino->a.field_counter,
-		start_desc_tbl = vino->a.start_desc_tbl,
-		next_4_desc = vino->a.next_4_desc;
-	unsigned int line_count_2,
-		page_index_2,
-		field_counter_2,
-		start_desc_tbl_2,
-		next_4_desc_2;
-#endif
-
-	spin_lock(&vino_drvdata->vino_lock);
-
-	while ((intr = vino->intr_status)) {
-		fc_a = vino->a.field_counter >> 1;
-		fc_b = vino->b.field_counter >> 1;
-
-		/* handle error-interrupts in some special way ?
-		 * --> skips frames */
-		if (intr & VINO_INTSTAT_A) {
-			if (intr & VINO_INTSTAT_A_EOF) {
-				vino_drvdata->a.field++;
-				if (vino_drvdata->a.field > 1) {
-					vino_dma_stop(&vino_drvdata->a);
-					vino_clear_interrupt(&vino_drvdata->a);
-					vino_drvdata->a.field = 0;
-					done_a = 1;
-				} else {
-					if (vino->a.page_index
-					    != vino_drvdata->a.line_size) {
-						vino->a.line_count = 0;
-						vino->a.page_index =
-							vino_drvdata->
-							a.line_size;
-						vino->a.next_4_desc =
-							vino->a.start_desc_tbl;
-					}
-				}
-				dprintk("channel A end-of-field "
-					"interrupt: %04x\n", intr);
-			} else {
-				vino_dma_stop(&vino_drvdata->a);
-				vino_clear_interrupt(&vino_drvdata->a);
-				vino_drvdata->a.field = 0;
-				skip_a = 1;
-				dprintk("channel A error interrupt: %04x\n",
-					intr);
-			}
-
-#ifdef VINO_DEBUG_INT
-			line_count_2 = vino->a.line_count;
-			page_index_2 = vino->a.page_index;
-			field_counter_2 = vino->a.field_counter;
-			start_desc_tbl_2 = vino->a.start_desc_tbl;
-			next_4_desc_2 = vino->a.next_4_desc;
-
-			printk("intr = %04x, loop = %d, field = %d\n",
-			       intr, loop, vino_drvdata->a.field);
-			printk("1- line count = %04d, page index = %04d, "
-			       "start = %08x, next = %08x\n"
-			       "   fieldc = %d, framec = %d\n",
-			       line_count, page_index, start_desc_tbl,
-			       next_4_desc, field_counter, fc_a);
-			printk("12-line count = %04d, page index = %04d, "
-			       "   start = %08x, next = %08x\n",
-			       line_count_2, page_index_2, start_desc_tbl_2,
-			       next_4_desc_2);
-
-			if (done_a)
-				printk("\n");
-#endif
-		}
-
-		if (intr & VINO_INTSTAT_B) {
-			if (intr & VINO_INTSTAT_B_EOF) {
-				vino_drvdata->b.field++;
-				if (vino_drvdata->b.field > 1) {
-					vino_dma_stop(&vino_drvdata->b);
-					vino_clear_interrupt(&vino_drvdata->b);
-					vino_drvdata->b.field = 0;
-					done_b = 1;
-				}
-				dprintk("channel B end-of-field "
-					"interrupt: %04x\n", intr);
-			} else {
-				vino_dma_stop(&vino_drvdata->b);
-				vino_clear_interrupt(&vino_drvdata->b);
-				vino_drvdata->b.field = 0;
-				skip_b = 1;
-				dprintk("channel B error interrupt: %04x\n",
-					intr);
-			}
-		}
-
-		/* Always remember to clear interrupt status.
-		 * Disable VINO interrupts while we do this. */
-		ctrl = vino->control;
-		vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
-		vino->intr_status = ~intr;
-		vino->control = ctrl;
-
-		spin_unlock(&vino_drvdata->vino_lock);
-
-		if ((!handled_a) && (done_a || skip_a)) {
-			if (!skip_a) {
-				v4l2_get_timestamp(
-					&vino_drvdata->a.int_data.timestamp);
-				vino_drvdata->a.int_data.frame_counter = fc_a;
-			}
-			vino_drvdata->a.int_data.skip = skip_a;
-
-			dprintk("channel A %s, interrupt: %d\n",
-				skip_a ? "skipping frame" : "frame done",
-				intr);
-			tasklet_hi_schedule(&vino_tasklet_a);
-			handled_a = 1;
-		}
-
-		if ((!handled_b) && (done_b || skip_b)) {
-			if (!skip_b) {
-				v4l2_get_timestamp(
-					&vino_drvdata->b.int_data.timestamp);
-				vino_drvdata->b.int_data.frame_counter = fc_b;
-			}
-			vino_drvdata->b.int_data.skip = skip_b;
-
-			dprintk("channel B %s, interrupt: %d\n",
-				skip_b ? "skipping frame" : "frame done",
-				intr);
-			tasklet_hi_schedule(&vino_tasklet_b);
-			handled_b = 1;
-		}
-
-#ifdef VINO_DEBUG_INT
-		loop++;
-#endif
-		spin_lock(&vino_drvdata->vino_lock);
-	}
-
-	spin_unlock(&vino_drvdata->vino_lock);
-
-	return IRQ_HANDLED;
-}
-
-/* VINO video input management */
-
-static int vino_get_saa7191_input(int input)
-{
-	switch (input) {
-	case VINO_INPUT_COMPOSITE:
-		return SAA7191_INPUT_COMPOSITE;
-	case VINO_INPUT_SVIDEO:
-		return SAA7191_INPUT_SVIDEO;
-	default:
-		printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
-		       "invalid input!\n");
-		return -1;
-	}
-}
-
-/* execute with input_lock locked */
-static int vino_is_input_owner(struct vino_channel_settings *vcs)
-{
-	switch(vcs->input) {
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO:
-		return vino_drvdata->decoder_owner == vcs->channel;
-	case VINO_INPUT_D1:
-		return vino_drvdata->camera_owner == vcs->channel;
-	default:
-		return 0;
-	}
-}
-
-static int vino_acquire_input(struct vino_channel_settings *vcs)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	dprintk("vino_acquire_input():\n");
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	/* First try D1 and then SAA7191 */
-	if (vino_drvdata->camera
-	    && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
-		vino_drvdata->camera_owner = vcs->channel;
-		vcs->input = VINO_INPUT_D1;
-		vcs->data_norm = VINO_DATA_NORM_D1;
-	} else if (vino_drvdata->decoder
-		   && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
-		int input;
-		int data_norm = 0;
-		v4l2_std_id norm;
-
-		input = VINO_INPUT_COMPOSITE;
-
-		ret = decoder_call(video, s_routing,
-				vino_get_saa7191_input(input), 0, 0);
-		if (ret) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-		/* Don't hold spinlocks while auto-detecting norm
-		 * as it may take a while... */
-
-		ret = decoder_call(video, querystd, &norm);
-		if (!ret) {
-			for (data_norm = 0; data_norm < 3; data_norm++) {
-				if (vino_data_norms[data_norm].std & norm)
-					break;
-			}
-			if (data_norm == 3)
-				data_norm = VINO_DATA_NORM_PAL;
-			ret = decoder_call(video, s_std, norm);
-		}
-
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-		if (ret) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		vino_drvdata->decoder_owner = vcs->channel;
-
-		vcs->input = input;
-		vcs->data_norm = data_norm;
-	} else {
-		vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
-			vino_drvdata->b.input : vino_drvdata->a.input;
-		vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
-			vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
-	}
-
-	if (vcs->input == VINO_INPUT_NONE) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	vino_set_default_clipping(vcs);
-	vino_set_default_scaling(vcs);
-	vino_set_default_framerate(vcs);
-
-	dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
-
-out:
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return ret;
-}
-
-static int vino_set_input(struct vino_channel_settings *vcs, int input)
-{
-	struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
-		&vino_drvdata->b : &vino_drvdata->a;
-	unsigned long flags;
-	int ret = 0;
-
-	dprintk("vino_set_input():\n");
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	if (vcs->input == input)
-		goto out;
-
-	switch (input) {
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO:
-		if (!vino_drvdata->decoder) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
-			vino_drvdata->decoder_owner = vcs->channel;
-		}
-
-		if (vino_drvdata->decoder_owner == vcs->channel) {
-			int data_norm = 0;
-			v4l2_std_id norm;
-
-			ret = decoder_call(video, s_routing,
-					vino_get_saa7191_input(input), 0, 0);
-			if (ret) {
-				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
-				ret = -EINVAL;
-				goto out;
-			}
-
-			spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-			/* Don't hold spinlocks while auto-detecting norm
-			 * as it may take a while... */
-
-			ret = decoder_call(video, querystd, &norm);
-			if (!ret) {
-				for (data_norm = 0; data_norm < 3; data_norm++) {
-					if (vino_data_norms[data_norm].std & norm)
-						break;
-				}
-				if (data_norm == 3)
-					data_norm = VINO_DATA_NORM_PAL;
-				ret = decoder_call(video, s_std, norm);
-			}
-
-			spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-			if (ret) {
-				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
-				ret = -EINVAL;
-				goto out;
-			}
-
-			vcs->input = input;
-			vcs->data_norm = data_norm;
-		} else {
-			if (input != vcs2->input) {
-				ret = -EBUSY;
-				goto out;
-			}
-
-			vcs->input = input;
-			vcs->data_norm = vcs2->data_norm;
-		}
-
-		if (vino_drvdata->camera_owner == vcs->channel) {
-			/* Transfer the ownership or release the input */
-			if (vcs2->input == VINO_INPUT_D1) {
-				vino_drvdata->camera_owner = vcs2->channel;
-			} else {
-				vino_drvdata->camera_owner = VINO_NO_CHANNEL;
-			}
-		}
-		break;
-	case VINO_INPUT_D1:
-		if (!vino_drvdata->camera) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
-			vino_drvdata->camera_owner = vcs->channel;
-
-		if (vino_drvdata->decoder_owner == vcs->channel) {
-			/* Transfer the ownership or release the input */
-			if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
-				 (vcs2->input == VINO_INPUT_SVIDEO)) {
-				vino_drvdata->decoder_owner = vcs2->channel;
-			} else {
-				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
-			}
-		}
-
-		vcs->input = input;
-		vcs->data_norm = VINO_DATA_NORM_D1;
-		break;
-	default:
-		ret = -EINVAL;
-		goto out;
-	}
-
-	vino_set_default_clipping(vcs);
-	vino_set_default_scaling(vcs);
-	vino_set_default_framerate(vcs);
-
-	dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
-
-out:
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return ret;
-}
-
-static void vino_release_input(struct vino_channel_settings *vcs)
-{
-	struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
-		&vino_drvdata->b : &vino_drvdata->a;
-	unsigned long flags;
-
-	dprintk("vino_release_input():\n");
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	/* Release ownership of the channel
-	 * and if the other channel takes input from
-	 * the same source, transfer the ownership */
-	if (vino_drvdata->camera_owner == vcs->channel) {
-		if (vcs2->input == VINO_INPUT_D1) {
-			vino_drvdata->camera_owner = vcs2->channel;
-		} else {
-			vino_drvdata->camera_owner = VINO_NO_CHANNEL;
-		}
-	} else if (vino_drvdata->decoder_owner == vcs->channel) {
-		if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
-			 (vcs2->input == VINO_INPUT_SVIDEO)) {
-			vino_drvdata->decoder_owner = vcs2->channel;
-		} else {
-			vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
-		}
-	}
-	vcs->input = VINO_INPUT_NONE;
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-}
-
-/* execute with input_lock locked */
-static int vino_set_data_norm(struct vino_channel_settings *vcs,
-			      unsigned int data_norm,
-			      unsigned long *flags)
-{
-	int err = 0;
-
-	if (data_norm == vcs->data_norm)
-		return 0;
-
-	switch (vcs->input) {
-	case VINO_INPUT_D1:
-		/* only one "norm" supported */
-		if (data_norm != VINO_DATA_NORM_D1)
-			return -EINVAL;
-		break;
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO: {
-		v4l2_std_id norm;
-
-		if ((data_norm != VINO_DATA_NORM_PAL)
-		    && (data_norm != VINO_DATA_NORM_NTSC)
-		    && (data_norm != VINO_DATA_NORM_SECAM))
-			return -EINVAL;
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
-
-		/* Don't hold spinlocks while setting norm
-		 * as it may take a while... */
-
-		norm = vino_data_norms[data_norm].std;
-		err = decoder_call(video, s_std, norm);
-
-		spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
-
-		if (err)
-			goto out;
-
-		vcs->data_norm = data_norm;
-
-		vino_set_default_clipping(vcs);
-		vino_set_default_scaling(vcs);
-		vino_set_default_framerate(vcs);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-
-out:
-	return err;
-}
-
-/* V4L2 helper functions */
-
-static int vino_find_data_format(__u32 pixelformat)
-{
-	int i;
-
-	for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
-		if (vino_data_formats[i].pixelformat == pixelformat)
-			return i;
-	}
-
-	return VINO_DATA_FMT_NONE;
-}
-
-static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
-{
-	int input = VINO_INPUT_NONE;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	if (vino_drvdata->decoder && vino_drvdata->camera) {
-		switch (index) {
-		case 0:
-			input = VINO_INPUT_COMPOSITE;
-			break;
-		case 1:
-			input = VINO_INPUT_SVIDEO;
-			break;
-		case 2:
-			input = VINO_INPUT_D1;
-			break;
-		}
-	} else if (vino_drvdata->decoder) {
-		switch (index) {
-		case 0:
-			input = VINO_INPUT_COMPOSITE;
-			break;
-		case 1:
-			input = VINO_INPUT_SVIDEO;
-			break;
-		}
-	} else if (vino_drvdata->camera) {
-		switch (index) {
-		case 0:
-			input = VINO_INPUT_D1;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return input;
-}
-
-/* execute with input_lock locked */
-static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
-{
-	__u32 index = 0;
-	// FIXME: detect when no inputs available
-
-	if (vino_drvdata->decoder && vino_drvdata->camera) {
-		switch (vcs->input) {
-		case VINO_INPUT_COMPOSITE:
-			index = 0;
-			break;
-		case VINO_INPUT_SVIDEO:
-			index = 1;
-			break;
-		case VINO_INPUT_D1:
-			index = 2;
-			break;
-		}
-	} else if (vino_drvdata->decoder) {
-		switch (vcs->input) {
-		case VINO_INPUT_COMPOSITE:
-			index = 0;
-			break;
-		case VINO_INPUT_SVIDEO:
-			index = 1;
-			break;
-		}
-	} else if (vino_drvdata->camera) {
-		switch (vcs->input) {
-		case VINO_INPUT_D1:
-			index = 0;
-			break;
-		}
-	}
-
-	return index;
-}
-
-/* V4L2 ioctls */
-
-static int vino_querycap(struct file *file, void *__fh,
-		struct v4l2_capability *cap)
-{
-	memset(cap, 0, sizeof(struct v4l2_capability));
-
-	strcpy(cap->driver, vino_driver_name);
-	strcpy(cap->card, vino_driver_description);
-	strcpy(cap->bus_info, vino_bus_name);
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int vino_enum_input(struct file *file, void *__fh,
-			       struct v4l2_input *i)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	__u32 index = i->index;
-	int input;
-	dprintk("requested index = %d\n", index);
-
-	input = vino_int_enum_input(vcs, index);
-	if (input == VINO_INPUT_NONE)
-		return -EINVAL;
-
-	i->type = V4L2_INPUT_TYPE_CAMERA;
-	i->std = vino_inputs[input].std;
-	strcpy(i->name, vino_inputs[input].name);
-
-	if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
-		decoder_call(video, g_input_status, &i->status);
-	return 0;
-}
-
-static int vino_g_input(struct file *file, void *__fh,
-			     unsigned int *i)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	__u32 index;
-	int input;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	input = vcs->input;
-	index = vino_find_input_index(vcs);
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	dprintk("input = %d\n", input);
-
-	if (input == VINO_INPUT_NONE) {
-		return -EINVAL;
-	}
-
-	*i = index;
-
-	return 0;
-}
-
-static int vino_s_input(struct file *file, void *__fh,
-			     unsigned int i)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	int input;
-	dprintk("requested input = %d\n", i);
-
-	input = vino_int_enum_input(vcs, i);
-	if (input == VINO_INPUT_NONE)
-		return -EINVAL;
-
-	return vino_set_input(vcs, input);
-}
-
-static int vino_querystd(struct file *file, void *__fh,
-			      v4l2_std_id *std)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	int err = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	switch (vcs->input) {
-	case VINO_INPUT_D1:
-		*std = vino_inputs[vcs->input].std;
-		break;
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO: {
-		decoder_call(video, querystd, std);
-		break;
-	}
-	default:
-		err = -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return err;
-}
-
-static int vino_g_std(struct file *file, void *__fh,
-			   v4l2_std_id *std)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	*std = vino_data_norms[vcs->data_norm].std;
-	dprintk("current standard = %d\n", vcs->data_norm);
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return 0;
-}
-
-static int vino_s_std(struct file *file, void *__fh,
-			   v4l2_std_id std)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	if (!vino_is_input_owner(vcs)) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	/* check if the standard is valid for the current input */
-	if (std & vino_inputs[vcs->input].std) {
-		dprintk("standard accepted\n");
-
-		/* change the video norm for SAA7191
-		 * and accept NTSC for D1 (do nothing) */
-
-		if (vcs->input == VINO_INPUT_D1)
-			goto out;
-
-		if (std & V4L2_STD_PAL) {
-			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
-						 &flags);
-		} else if (std & V4L2_STD_NTSC) {
-			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
-						 &flags);
-		} else if (std & V4L2_STD_SECAM) {
-			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
-						 &flags);
-		} else {
-			ret = -EINVAL;
-		}
-
-		if (ret) {
-			ret = -EINVAL;
-		}
-	} else {
-		ret = -EINVAL;
-	}
-
-out:
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return ret;
-}
-
-static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
-			      struct v4l2_fmtdesc *fd)
-{
-	dprintk("format index = %d\n", fd->index);
-
-	if (fd->index >= VINO_DATA_FMT_COUNT)
-		return -EINVAL;
-	dprintk("format name = %s\n", vino_data_formats[fd->index].description);
-
-	fd->pixelformat = vino_data_formats[fd->index].pixelformat;
-	strcpy(fd->description, vino_data_formats[fd->index].description);
-	return 0;
-}
-
-static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
-			     struct v4l2_format *f)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	struct vino_channel_settings tempvcs;
-	unsigned long flags;
-	struct v4l2_pix_format *pf = &f->fmt.pix;
-
-	dprintk("requested: w = %d, h = %d\n",
-			pf->width, pf->height);
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	tempvcs.data_format = vino_find_data_format(pf->pixelformat);
-	if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
-		tempvcs.data_format = VINO_DATA_FMT_GREY;
-		pf->pixelformat =
-			vino_data_formats[tempvcs.data_format].
-			pixelformat;
-	}
-
-	/* data format must be set before clipping/scaling */
-	vino_set_scaling(&tempvcs, pf->width, pf->height);
-
-	dprintk("data format = %s\n",
-			vino_data_formats[tempvcs.data_format].description);
-
-	pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
-		tempvcs.decimation;
-	pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
-		tempvcs.decimation;
-
-	pf->field = V4L2_FIELD_INTERLACED;
-	pf->bytesperline = tempvcs.line_size;
-	pf->sizeimage = tempvcs.line_size *
-		(tempvcs.clipping.bottom - tempvcs.clipping.top) /
-		tempvcs.decimation;
-	pf->colorspace =
-		vino_data_formats[tempvcs.data_format].colorspace;
-
-	return 0;
-}
-
-static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
-			   struct v4l2_format *f)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	struct v4l2_pix_format *pf = &f->fmt.pix;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	pf->width = (vcs->clipping.right - vcs->clipping.left) /
-		vcs->decimation;
-	pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
-		vcs->decimation;
-	pf->pixelformat =
-		vino_data_formats[vcs->data_format].pixelformat;
-
-	pf->field = V4L2_FIELD_INTERLACED;
-	pf->bytesperline = vcs->line_size;
-	pf->sizeimage = vcs->line_size *
-		(vcs->clipping.bottom - vcs->clipping.top) /
-		vcs->decimation;
-	pf->colorspace =
-		vino_data_formats[vcs->data_format].colorspace;
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-	return 0;
-}
-
-static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
-			   struct v4l2_format *f)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	int data_format;
-	unsigned long flags;
-	struct v4l2_pix_format *pf = &f->fmt.pix;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	data_format = vino_find_data_format(pf->pixelformat);
-
-	if (data_format == VINO_DATA_FMT_NONE) {
-		vcs->data_format = VINO_DATA_FMT_GREY;
-		pf->pixelformat =
-			vino_data_formats[vcs->data_format].
-			pixelformat;
-	} else {
-		vcs->data_format = data_format;
-	}
-
-	/* data format must be set before clipping/scaling */
-	vino_set_scaling(vcs, pf->width, pf->height);
-
-	dprintk("data format = %s\n",
-	       vino_data_formats[vcs->data_format].description);
-
-	pf->width = vcs->clipping.right - vcs->clipping.left;
-	pf->height = vcs->clipping.bottom - vcs->clipping.top;
-
-	pf->field = V4L2_FIELD_INTERLACED;
-	pf->bytesperline = vcs->line_size;
-	pf->sizeimage = vcs->line_size *
-		(vcs->clipping.bottom - vcs->clipping.top) /
-		vcs->decimation;
-	pf->colorspace =
-		vino_data_formats[vcs->data_format].colorspace;
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-	return 0;
-}
-
-static int vino_cropcap(struct file *file, void *__fh,
-			     struct v4l2_cropcap *ccap)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	const struct vino_data_norm *norm;
-	unsigned long flags;
-
-	switch (ccap->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-		norm = &vino_data_norms[vcs->data_norm];
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-		ccap->bounds.left = 0;
-		ccap->bounds.top = 0;
-		ccap->bounds.width = norm->width;
-		ccap->bounds.height = norm->height;
-		memcpy(&ccap->defrect, &ccap->bounds,
-		       sizeof(struct v4l2_rect));
-
-		ccap->pixelaspect.numerator = 1;
-		ccap->pixelaspect.denominator = 1;
-		break;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int vino_g_crop(struct file *file, void *__fh,
-			    struct v4l2_crop *c)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-
-	switch (c->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-		c->c.left = vcs->clipping.left;
-		c->c.top = vcs->clipping.top;
-		c->c.width = vcs->clipping.right - vcs->clipping.left;
-		c->c.height = vcs->clipping.bottom - vcs->clipping.top;
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-		break;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int vino_s_crop(struct file *file, void *__fh,
-			    const struct v4l2_crop *c)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-
-	switch (c->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-		vino_set_clipping(vcs, c->c.left, c->c.top,
-				  c->c.width, c->c.height);
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-		break;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int vino_g_parm(struct file *file, void *__fh,
-			    struct v4l2_streamparm *sp)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	struct v4l2_captureparm *cp = &sp->parm.capture;
-
-	cp->capability = V4L2_CAP_TIMEPERFRAME;
-	cp->timeperframe.numerator = 1;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	cp->timeperframe.denominator = vcs->fps;
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	/* TODO: cp->readbuffers = xxx; */
-
-	return 0;
-}
-
-static int vino_s_parm(struct file *file, void *__fh,
-			    struct v4l2_streamparm *sp)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	struct v4l2_captureparm *cp = &sp->parm.capture;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	if ((cp->timeperframe.numerator == 0) ||
-	    (cp->timeperframe.denominator == 0)) {
-		/* reset framerate */
-		vino_set_default_framerate(vcs);
-	} else {
-		vino_set_framerate(vcs, cp->timeperframe.denominator /
-				   cp->timeperframe.numerator);
-	}
-
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return 0;
-}
-
-static int vino_reqbufs(struct file *file, void *__fh,
-			     struct v4l2_requestbuffers *rb)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-
-	if (vcs->reading)
-		return -EBUSY;
-
-	/* TODO: check queue type */
-	if (rb->memory != V4L2_MEMORY_MMAP) {
-		dprintk("type not mmap\n");
-		return -EINVAL;
-	}
-
-	dprintk("count = %d\n", rb->count);
-	if (rb->count > 0) {
-		if (vino_is_capturing(vcs)) {
-			dprintk("busy, capturing\n");
-			return -EBUSY;
-		}
-
-		if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
-			dprintk("busy, buffers still mapped\n");
-			return -EBUSY;
-		} else {
-			vcs->streaming = 0;
-			vino_queue_free(&vcs->fb_queue);
-			vino_queue_init(&vcs->fb_queue, &rb->count);
-		}
-	} else {
-		vcs->streaming = 0;
-		vino_capture_stop(vcs);
-		vino_queue_free(&vcs->fb_queue);
-	}
-
-	return 0;
-}
-
-static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
-					struct vino_framebuffer *fb,
-					struct v4l2_buffer *b)
-{
-	if (vino_queue_outgoing_contains(&vcs->fb_queue,
-					 fb->id)) {
-		b->flags &= ~V4L2_BUF_FLAG_QUEUED;
-		b->flags |= V4L2_BUF_FLAG_DONE;
-	} else if (vino_queue_incoming_contains(&vcs->fb_queue,
-				       fb->id)) {
-		b->flags &= ~V4L2_BUF_FLAG_DONE;
-		b->flags |= V4L2_BUF_FLAG_QUEUED;
-	} else {
-		b->flags &= ~(V4L2_BUF_FLAG_DONE |
-			      V4L2_BUF_FLAG_QUEUED);
-	}
-
-	b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
-
-	if (fb->map_count > 0)
-		b->flags |= V4L2_BUF_FLAG_MAPPED;
-
-	b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK;
-	b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-
-	b->index = fb->id;
-	b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
-		V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
-	b->m.offset = fb->offset;
-	b->bytesused = fb->data_size;
-	b->length = fb->size;
-	b->field = V4L2_FIELD_INTERLACED;
-	b->sequence = fb->frame_counter;
-	memcpy(&b->timestamp, &fb->timestamp,
-	       sizeof(struct timeval));
-	// b->input ?
-
-	dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
-		fb->id, fb->size, fb->data_size, fb->offset);
-}
-
-static int vino_querybuf(struct file *file, void *__fh,
-			      struct v4l2_buffer *b)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	struct vino_framebuffer *fb;
-
-	if (vcs->reading)
-		return -EBUSY;
-
-	/* TODO: check queue type */
-	if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
-		dprintk("invalid index = %d\n",
-		       b->index);
-		return -EINVAL;
-	}
-
-	fb = vino_queue_get_buffer(&vcs->fb_queue,
-				   b->index);
-	if (fb == NULL) {
-		dprintk("vino_queue_get_buffer() failed");
-		return -EINVAL;
-	}
-
-	vino_v4l2_get_buffer_status(vcs, fb, b);
-
-	return 0;
-}
-
-static int vino_qbuf(struct file *file, void *__fh,
-			  struct v4l2_buffer *b)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	struct vino_framebuffer *fb;
-	int ret;
-
-	if (vcs->reading)
-		return -EBUSY;
-
-	/* TODO: check queue type */
-	if (b->memory != V4L2_MEMORY_MMAP) {
-		dprintk("type not mmap\n");
-		return -EINVAL;
-	}
-
-	fb = vino_capture_enqueue(vcs, b->index);
-	if (fb == NULL)
-		return -EINVAL;
-
-	vino_v4l2_get_buffer_status(vcs, fb, b);
-
-	if (vcs->streaming) {
-		ret = vino_capture_next(vcs, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int vino_dqbuf(struct file *file, void *__fh,
-			   struct v4l2_buffer *b)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned int nonblocking = file->f_flags & O_NONBLOCK;
-	struct vino_framebuffer *fb;
-	unsigned int incoming, outgoing;
-	int err;
-
-	if (vcs->reading)
-		return -EBUSY;
-
-	/* TODO: check queue type */
-
-	err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
-	if (err) {
-		dprintk("vino_queue_get_incoming() failed\n");
-		return -EINVAL;
-	}
-	err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
-	if (err) {
-		dprintk("vino_queue_get_outgoing() failed\n");
-		return -EINVAL;
-	}
-
-	dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
-
-	if (outgoing == 0) {
-		if (incoming == 0) {
-			dprintk("no incoming or outgoing buffers\n");
-			return -EINVAL;
-		}
-		if (nonblocking) {
-			dprintk("non-blocking I/O was selected and "
-				"there are no buffers to dequeue\n");
-			return -EAGAIN;
-		}
-
-		err = vino_wait_for_frame(vcs);
-		if (err) {
-			err = vino_wait_for_frame(vcs);
-			if (err) {
-				/* interrupted or no frames captured because of
-				 * frame skipping */
-				/* vino_capture_failed(vcs); */
-				return -EIO;
-			}
-		}
-	}
-
-	fb = vino_queue_remove(&vcs->fb_queue, &b->index);
-	if (fb == NULL) {
-		dprintk("vino_queue_remove() failed\n");
-		return -EINVAL;
-	}
-
-	err = vino_check_buffer(vcs, fb);
-
-	vino_v4l2_get_buffer_status(vcs, fb, b);
-
-	if (err)
-		return -EIO;
-
-	return 0;
-}
-
-static int vino_streamon(struct file *file, void *__fh,
-		enum v4l2_buf_type i)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned int incoming;
-	int ret;
-	if (vcs->reading)
-		return -EBUSY;
-
-	if (vcs->streaming)
-		return 0;
-
-	// TODO: check queue type
-
-	if (vino_queue_get_length(&vcs->fb_queue) < 1) {
-		dprintk("no buffers allocated\n");
-		return -EINVAL;
-	}
-
-	ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
-	if (ret) {
-		dprintk("vino_queue_get_incoming() failed\n");
-		return -EINVAL;
-	}
-
-	vcs->streaming = 1;
-
-	if (incoming > 0) {
-		ret = vino_capture_next(vcs, 1);
-		if (ret) {
-			vcs->streaming = 0;
-
-			dprintk("couldn't start capture\n");
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int vino_streamoff(struct file *file, void *__fh,
-		enum v4l2_buf_type i)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	if (vcs->reading)
-		return -EBUSY;
-
-	if (!vcs->streaming)
-		return 0;
-
-	vcs->streaming = 0;
-	vino_capture_stop(vcs);
-
-	return 0;
-}
-
-static int vino_queryctrl(struct file *file, void *__fh,
-			       struct v4l2_queryctrl *queryctrl)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	int i;
-	int err = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	switch (vcs->input) {
-	case VINO_INPUT_D1:
-		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
-			if (vino_indycam_v4l2_controls[i].id ==
-			    queryctrl->id) {
-				memcpy(queryctrl,
-				       &vino_indycam_v4l2_controls[i],
-				       sizeof(struct v4l2_queryctrl));
-				queryctrl->reserved[0] = 0;
-				goto found;
-			}
-		}
-
-		err =  -EINVAL;
-		break;
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO:
-		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
-			if (vino_saa7191_v4l2_controls[i].id ==
-			    queryctrl->id) {
-				memcpy(queryctrl,
-				       &vino_saa7191_v4l2_controls[i],
-				       sizeof(struct v4l2_queryctrl));
-				queryctrl->reserved[0] = 0;
-				goto found;
-			}
-		}
-
-		err =  -EINVAL;
-		break;
-	default:
-		err =  -EINVAL;
-	}
-
- found:
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return err;
-}
-
-static int vino_g_ctrl(struct file *file, void *__fh,
-			    struct v4l2_control *control)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	int i;
-	int err = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	switch (vcs->input) {
-	case VINO_INPUT_D1: {
-		err = -EINVAL;
-		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
-			if (vino_indycam_v4l2_controls[i].id == control->id) {
-				err = 0;
-				break;
-			}
-		}
-
-		if (err)
-			goto out;
-
-		err = camera_call(core, g_ctrl, control);
-		if (err)
-			err = -EINVAL;
-		break;
-	}
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO: {
-		err = -EINVAL;
-		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
-			if (vino_saa7191_v4l2_controls[i].id == control->id) {
-				err = 0;
-				break;
-			}
-		}
-
-		if (err)
-			goto out;
-
-		err = decoder_call(core, g_ctrl, control);
-		if (err)
-			err = -EINVAL;
-		break;
-	}
-	default:
-		err =  -EINVAL;
-	}
-
-out:
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return err;
-}
-
-static int vino_s_ctrl(struct file *file, void *__fh,
-			    struct v4l2_control *control)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned long flags;
-	int i;
-	int err = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-	if (!vino_is_input_owner(vcs)) {
-		err = -EBUSY;
-		goto out;
-	}
-
-	switch (vcs->input) {
-	case VINO_INPUT_D1: {
-		err = -EINVAL;
-		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
-			if (vino_indycam_v4l2_controls[i].id == control->id) {
-				err = 0;
-				break;
-			}
-		}
-		if (err)
-			goto out;
-		if (control->value < vino_indycam_v4l2_controls[i].minimum ||
-		    control->value > vino_indycam_v4l2_controls[i].maximum) {
-			err = -ERANGE;
-			goto out;
-		}
-		err = camera_call(core, s_ctrl, control);
-		if (err)
-			err = -EINVAL;
-		break;
-	}
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO: {
-		err = -EINVAL;
-		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
-			if (vino_saa7191_v4l2_controls[i].id == control->id) {
-				err = 0;
-				break;
-			}
-		}
-		if (err)
-			goto out;
-		if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
-		    control->value > vino_saa7191_v4l2_controls[i].maximum) {
-			err = -ERANGE;
-			goto out;
-		}
-
-		err = decoder_call(core, s_ctrl, control);
-		if (err)
-			err = -EINVAL;
-		break;
-	}
-	default:
-		err =  -EINVAL;
-	}
-
-out:
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return err;
-}
-
-/* File operations */
-
-static int vino_open(struct file *file)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	int ret = 0;
-	dprintk("open(): channel = %c\n",
-	       (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
-
-	mutex_lock(&vcs->mutex);
-
-	if (vcs->users) {
-		dprintk("open(): driver busy\n");
-		ret = -EBUSY;
-		goto out;
-	}
-
-	ret = vino_acquire_input(vcs);
-	if (ret) {
-		dprintk("open(): vino_acquire_input() failed\n");
-		goto out;
-	}
-
-	vcs->users++;
-
- out:
-	mutex_unlock(&vcs->mutex);
-
-	dprintk("open(): %s!\n", ret ? "failed" : "complete");
-
-	return ret;
-}
-
-static int vino_close(struct file *file)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	dprintk("close():\n");
-
-	mutex_lock(&vcs->mutex);
-
-	vcs->users--;
-
-	if (!vcs->users) {
-		vino_release_input(vcs);
-
-		/* stop DMA and free buffers */
-		vino_capture_stop(vcs);
-		vino_queue_free(&vcs->fb_queue);
-	}
-
-	mutex_unlock(&vcs->mutex);
-
-	return 0;
-}
-
-static void vino_vm_open(struct vm_area_struct *vma)
-{
-	struct vino_framebuffer *fb = vma->vm_private_data;
-
-	fb->map_count++;
-	dprintk("vino_vm_open(): count = %d\n", fb->map_count);
-}
-
-static void vino_vm_close(struct vm_area_struct *vma)
-{
-	struct vino_framebuffer *fb = vma->vm_private_data;
-
-	fb->map_count--;
-	dprintk("vino_vm_close(): count = %d\n", fb->map_count);
-}
-
-static const struct vm_operations_struct vino_vm_ops = {
-	.open	= vino_vm_open,
-	.close	= vino_vm_close,
-};
-
-static int vino_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-
-	unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-
-	struct vino_framebuffer *fb = NULL;
-	unsigned int i, length;
-	int ret = 0;
-
-	dprintk("mmap():\n");
-
-	// TODO: reject mmap if already mapped
-
-	if (mutex_lock_interruptible(&vcs->mutex))
-		return -EINTR;
-
-	if (vcs->reading) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	// TODO: check queue type
-
-	if (!(vma->vm_flags & VM_WRITE)) {
-		dprintk("mmap(): app bug: PROT_WRITE please\n");
-		ret = -EINVAL;
-		goto out;
-	}
-	if (!(vma->vm_flags & VM_SHARED)) {
-		dprintk("mmap(): app bug: MAP_SHARED please\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* find the correct buffer using offset */
-	length = vino_queue_get_length(&vcs->fb_queue);
-	if (length == 0) {
-		dprintk("mmap(): queue not initialized\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	for (i = 0; i < length; i++) {
-		fb = vino_queue_get_buffer(&vcs->fb_queue, i);
-		if (fb == NULL) {
-			dprintk("mmap(): vino_queue_get_buffer() failed\n");
-			ret = -EINVAL;
-			goto out;
-		}
-
-		if (fb->offset == offset)
-			goto found;
-	}
-
-	dprintk("mmap(): invalid offset = %lu\n", offset);
-	ret = -EINVAL;
-	goto out;
-
-found:
-	dprintk("mmap(): buffer = %d\n", i);
-
-	if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
-		dprintk("mmap(): failed: size = %lu > %lu\n",
-			size, fb->desc_table.page_count * PAGE_SIZE);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	for (i = 0; i < fb->desc_table.page_count; i++) {
-		unsigned long pfn =
-			virt_to_phys((void *)fb->desc_table.virtual[i]) >>
-			PAGE_SHIFT;
-
-		if (size < PAGE_SIZE)
-			break;
-
-		// protection was: PAGE_READONLY
-		if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
-				    vma->vm_page_prot)) {
-			dprintk("mmap(): remap_pfn_range() failed\n");
-			ret = -EAGAIN;
-			goto out;
-		}
-
-		start += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	fb->map_count = 1;
-
-	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-	vma->vm_flags &= ~VM_IO;
-	vma->vm_private_data = fb;
-	vma->vm_file = file;
-	vma->vm_ops = &vino_vm_ops;
-
-out:
-	mutex_unlock(&vcs->mutex);
-
-	return ret;
-}
-
-static unsigned int vino_poll(struct file *file, poll_table *pt)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	unsigned int outgoing;
-	unsigned int ret = 0;
-
-	// lock mutex (?)
-	// TODO: this has to be corrected for different read modes
-
-	dprintk("poll():\n");
-
-	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
-		dprintk("poll(): vino_queue_get_outgoing() failed\n");
-		ret = POLLERR;
-		goto error;
-	}
-	if (outgoing > 0)
-		goto over;
-
-	poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
-
-	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
-		dprintk("poll(): vino_queue_get_outgoing() failed\n");
-		ret = POLLERR;
-		goto error;
-	}
-
-over:
-	dprintk("poll(): data %savailable\n",
-		(outgoing > 0) ? "" : "not ");
-
-	if (outgoing > 0)
-		ret = POLLIN | POLLRDNORM;
-
-error:
-	return ret;
-}
-
-static long vino_ioctl(struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-	long ret;
-
-	if (mutex_lock_interruptible(&vcs->mutex))
-		return -EINTR;
-
-	ret = video_ioctl2(file, cmd, arg);
-
-	mutex_unlock(&vcs->mutex);
-
-	return ret;
-}
-
-/* Initialization and cleanup */
-
-/* __initdata */
-static int vino_init_stage;
-
-const struct v4l2_ioctl_ops vino_ioctl_ops = {
-	.vidioc_enum_fmt_vid_cap     = vino_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap 	     = vino_g_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap  	     = vino_s_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap	     = vino_try_fmt_vid_cap,
-	.vidioc_querycap    	     = vino_querycap,
-	.vidioc_enum_input   	     = vino_enum_input,
-	.vidioc_g_input      	     = vino_g_input,
-	.vidioc_s_input      	     = vino_s_input,
-	.vidioc_g_std 		     = vino_g_std,
-	.vidioc_s_std 		     = vino_s_std,
-	.vidioc_querystd             = vino_querystd,
-	.vidioc_cropcap      	     = vino_cropcap,
-	.vidioc_s_crop       	     = vino_s_crop,
-	.vidioc_g_crop       	     = vino_g_crop,
-	.vidioc_s_parm 		     = vino_s_parm,
-	.vidioc_g_parm 		     = vino_g_parm,
-	.vidioc_reqbufs              = vino_reqbufs,
-	.vidioc_querybuf             = vino_querybuf,
-	.vidioc_qbuf                 = vino_qbuf,
-	.vidioc_dqbuf                = vino_dqbuf,
-	.vidioc_streamon             = vino_streamon,
-	.vidioc_streamoff            = vino_streamoff,
-	.vidioc_queryctrl            = vino_queryctrl,
-	.vidioc_g_ctrl               = vino_g_ctrl,
-	.vidioc_s_ctrl               = vino_s_ctrl,
-};
-
-static const struct v4l2_file_operations vino_fops = {
-	.owner		= THIS_MODULE,
-	.open		= vino_open,
-	.release	= vino_close,
-	.unlocked_ioctl	= vino_ioctl,
-	.mmap		= vino_mmap,
-	.poll		= vino_poll,
-};
-
-static struct video_device vdev_template = {
-	.name		= "NOT SET",
-	.fops		= &vino_fops,
-	.ioctl_ops 	= &vino_ioctl_ops,
-	.tvnorms 	= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
-};
-
-static void vino_module_cleanup(int stage)
-{
-	switch(stage) {
-	case 11:
-		video_unregister_device(vino_drvdata->b.vdev);
-		vino_drvdata->b.vdev = NULL;
-	case 10:
-		video_unregister_device(vino_drvdata->a.vdev);
-		vino_drvdata->a.vdev = NULL;
-	case 9:
-		i2c_del_adapter(&vino_i2c_adapter);
-	case 8:
-		free_irq(SGI_VINO_IRQ, NULL);
-	case 7:
-		if (vino_drvdata->b.vdev) {
-			video_device_release(vino_drvdata->b.vdev);
-			vino_drvdata->b.vdev = NULL;
-		}
-	case 6:
-		if (vino_drvdata->a.vdev) {
-			video_device_release(vino_drvdata->a.vdev);
-			vino_drvdata->a.vdev = NULL;
-		}
-	case 5:
-		/* all entries in dma_cpu dummy table have the same address */
-		dma_unmap_single(NULL,
-				 vino_drvdata->dummy_desc_table.dma_cpu[0],
-				 PAGE_SIZE, DMA_FROM_DEVICE);
-		dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
-				  * sizeof(dma_addr_t),
-				  (void *)vino_drvdata->
-				  dummy_desc_table.dma_cpu,
-				  vino_drvdata->dummy_desc_table.dma);
-	case 4:
-		free_page(vino_drvdata->dummy_page);
-	case 3:
-		v4l2_device_unregister(&vino_drvdata->v4l2_dev);
-	case 2:
-		kfree(vino_drvdata);
-	case 1:
-		iounmap(vino);
-	case 0:
-		break;
-	default:
-		dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
-			stage);
-	}
-}
-
-static int vino_probe(void)
-{
-	unsigned long rev_id;
-
-	if (ip22_is_fullhouse()) {
-		printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
-		return -ENODEV;
-	}
-
-	if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
-		printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
-		return -ENODEV;
-	}
-
-	vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
-	if (!vino) {
-		printk(KERN_ERR "VINO: ioremap() failed\n");
-		return -EIO;
-	}
-	vino_init_stage++;
-
-	if (get_dbe(rev_id, &(vino->rev_id))) {
-		printk(KERN_ERR "Failed to read VINO revision register\n");
-		vino_module_cleanup(vino_init_stage);
-		return -ENODEV;
-	}
-
-	if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
-		printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
-		       rev_id);
-		vino_module_cleanup(vino_init_stage);
-		return -ENODEV;
-	}
-
-	printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
-
-	return 0;
-}
-
-static int vino_init(void)
-{
-	dma_addr_t dma_dummy_address;
-	int err;
-	int i;
-
-	vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
-	if (!vino_drvdata) {
-		vino_module_cleanup(vino_init_stage);
-		return -ENOMEM;
-	}
-	vino_init_stage++;
-	strlcpy(vino_drvdata->v4l2_dev.name, "vino",
-			sizeof(vino_drvdata->v4l2_dev.name));
-	err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
-	if (err)
-		return err;
-	vino_init_stage++;
-
-	/* create a dummy dma descriptor */
-	vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
-	if (!vino_drvdata->dummy_page) {
-		vino_module_cleanup(vino_init_stage);
-		return -ENOMEM;
-	}
-	vino_init_stage++;
-
-	// TODO: use page_count in dummy_desc_table
-
-	vino_drvdata->dummy_desc_table.dma_cpu =
-		dma_alloc_coherent(NULL,
-		VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
-		&vino_drvdata->dummy_desc_table.dma,
-		GFP_KERNEL | GFP_DMA);
-	if (!vino_drvdata->dummy_desc_table.dma_cpu) {
-		vino_module_cleanup(vino_init_stage);
-		return -ENOMEM;
-	}
-	vino_init_stage++;
-
-	dma_dummy_address = dma_map_single(NULL,
-					   (void *)vino_drvdata->dummy_page,
-					PAGE_SIZE, DMA_FROM_DEVICE);
-	for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
-		vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
-	}
-
-	/* initialize VINO */
-
-	vino->control = 0;
-	vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
-	vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
-	udelay(VINO_DESC_FETCH_DELAY);
-
-	vino->intr_status = 0;
-
-	vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
-	vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
-
-	return 0;
-}
-
-static int vino_init_channel_settings(struct vino_channel_settings *vcs,
-				 unsigned int channel, const char *name)
-{
-	vcs->channel = channel;
-	vcs->input = VINO_INPUT_NONE;
-	vcs->alpha = 0;
-	vcs->users = 0;
-	vcs->data_format = VINO_DATA_FMT_GREY;
-	vcs->data_norm = VINO_DATA_NORM_NTSC;
-	vcs->decimation = 1;
-	vino_set_default_clipping(vcs);
-	vino_set_default_framerate(vcs);
-
-	vcs->capturing = 0;
-
-	mutex_init(&vcs->mutex);
-	spin_lock_init(&vcs->capture_lock);
-
-	mutex_init(&vcs->fb_queue.queue_mutex);
-	spin_lock_init(&vcs->fb_queue.queue_lock);
-	init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
-
-	vcs->vdev = video_device_alloc();
-	if (!vcs->vdev) {
-		vino_module_cleanup(vino_init_stage);
-		return -ENOMEM;
-	}
-	vino_init_stage++;
-
-	memcpy(vcs->vdev, &vdev_template,
-	       sizeof(struct video_device));
-	strcpy(vcs->vdev->name, name);
-	vcs->vdev->release = video_device_release;
-	vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
-
-	video_set_drvdata(vcs->vdev, vcs);
-
-	return 0;
-}
-
-static int __init vino_module_init(void)
-{
-	int ret;
-
-	printk(KERN_INFO "SGI VINO driver version %s\n",
-	       VINO_MODULE_VERSION);
-
-	ret = vino_probe();
-	if (ret)
-		return ret;
-
-	ret = vino_init();
-	if (ret)
-		return ret;
-
-	/* initialize data structures */
-
-	spin_lock_init(&vino_drvdata->vino_lock);
-	spin_lock_init(&vino_drvdata->input_lock);
-
-	ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
-				    vino_vdev_name_a);
-	if (ret)
-		return ret;
-
-	ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
-				    vino_vdev_name_b);
-	if (ret)
-		return ret;
-
-	/* initialize hardware and register V4L devices */
-
-	ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
-		vino_driver_description, NULL);
-	if (ret) {
-		printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
-		       SGI_VINO_IRQ);
-		vino_module_cleanup(vino_init_stage);
-		return -EAGAIN;
-	}
-	vino_init_stage++;
-
-	ret = i2c_add_adapter(&vino_i2c_adapter);
-	if (ret) {
-		printk(KERN_ERR "VINO I2C bus registration failed\n");
-		vino_module_cleanup(vino_init_stage);
-		return ret;
-	}
-	i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
-	vino_init_stage++;
-
-	ret = video_register_device(vino_drvdata->a.vdev,
-				    VFL_TYPE_GRABBER, -1);
-	if (ret < 0) {
-		printk(KERN_ERR "VINO channel A Video4Linux-device "
-		       "registration failed\n");
-		vino_module_cleanup(vino_init_stage);
-		return -EINVAL;
-	}
-	vino_init_stage++;
-
-	ret = video_register_device(vino_drvdata->b.vdev,
-				    VFL_TYPE_GRABBER, -1);
-	if (ret < 0) {
-		printk(KERN_ERR "VINO channel B Video4Linux-device "
-		       "registration failed\n");
-		vino_module_cleanup(vino_init_stage);
-		return -EINVAL;
-	}
-	vino_init_stage++;
-
-	vino_drvdata->decoder =
-		v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
-			       "saa7191", 0, I2C_ADDRS(0x45));
-	vino_drvdata->camera =
-		v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
-			       "indycam", 0, I2C_ADDRS(0x2b));
-
-	dprintk("init complete!\n");
-
-	return 0;
-}
-
-static void __exit vino_module_exit(void)
-{
-	dprintk("exiting, stage = %d ...\n", vino_init_stage);
-	vino_module_cleanup(vino_init_stage);
-	dprintk("cleanup complete, exit!\n");
-}
-
-module_init(vino_module_init);
-module_exit(vino_module_exit);
diff --git a/drivers/staging/media/vino/vino.h b/drivers/staging/media/vino/vino.h
deleted file mode 100644
index de2d615ae7c9..000000000000
--- a/drivers/staging/media/vino/vino.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Driver for the VINO (Video In No Out) system found in SGI Indys.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
- * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
- */
-
-#ifndef _VINO_H_
-#define _VINO_H_
-
-#define VINO_BASE	0x00080000	/* Vino is in the EISA address space,
-					 * but it is not an EISA bus card */
-#define VINO_PAGE_SIZE	4096
-
-struct sgi_vino_channel {
-	u32 _pad_alpha;
-	volatile u32 alpha;
-
-#define VINO_CLIP_X(x)		((x) & 0x3ff)		/* bits 0:9 */
-#define VINO_CLIP_ODD(x)	(((x) & 0x1ff) << 10)	/* bits 10:18 */
-#define VINO_CLIP_EVEN(x)	(((x) & 0x1ff) << 19)	/* bits 19:27 */
-	u32 _pad_clip_start;
-	volatile u32 clip_start;
-	u32 _pad_clip_end;
-	volatile u32 clip_end;
-
-#define VINO_FRAMERT_FULL	0xfff
-#define VINO_FRAMERT_PAL	(1<<0)			/* 0=NTSC 1=PAL */
-#define VINO_FRAMERT_RT(x)	(((x) & 0xfff) << 1)	/* bits 1:12 */
-	u32 _pad_frame_rate;
-	volatile u32 frame_rate;
-
-	u32 _pad_field_counter;
-	volatile u32 field_counter;
-	u32 _pad_line_size;
-	volatile u32 line_size;
-	u32 _pad_line_count;
-	volatile u32 line_count;
-	u32 _pad_page_index;
-	volatile u32 page_index;
-	u32 _pad_next_4_desc;
-	volatile u32 next_4_desc;
-	u32 _pad_start_desc_tbl;
-	volatile u32 start_desc_tbl;
-
-#define VINO_DESC_JUMP		(1<<30)
-#define VINO_DESC_STOP		(1<<31)
-#define VINO_DESC_VALID		(1<<32)
-	u32 _pad_desc_0;
-	volatile u32 desc_0;
-	u32 _pad_desc_1;
-	volatile u32 desc_1;
-	u32 _pad_desc_2;
-	volatile u32 desc_2;
-	u32 _pad_Bdesc_3;
-	volatile u32 desc_3;
-
-	u32 _pad_fifo_thres;
-	volatile u32 fifo_thres;
-	u32 _pad_fifo_read;
-	volatile u32 fifo_read;
-	u32 _pad_fifo_write;
-	volatile u32 fifo_write;
-};
-
-struct sgi_vino {
-#define VINO_CHIP_ID		0xb
-#define VINO_REV_NUM(x)		((x) & 0x0f)
-#define VINO_ID_VALUE(x)	(((x) & 0xf0) >> 4)
-	u32 _pad_rev_id;
-	volatile u32 rev_id;
-
-#define VINO_CTRL_LITTLE_ENDIAN		(1<<0)
-#define VINO_CTRL_A_EOF_INT		(1<<1)	/* Field transferred int */
-#define VINO_CTRL_A_FIFO_INT		(1<<2)	/* FIFO overflow int */
-#define VINO_CTRL_A_EOD_INT		(1<<3)	/* End of desc table int */
-#define VINO_CTRL_A_INT			(VINO_CTRL_A_EOF_INT | \
-					 VINO_CTRL_A_FIFO_INT | \
-					 VINO_CTRL_A_EOD_INT)
-#define VINO_CTRL_B_EOF_INT		(1<<4)	/* Field transferred int */
-#define VINO_CTRL_B_FIFO_INT		(1<<5)	/* FIFO overflow int */
-#define VINO_CTRL_B_EOD_INT		(1<<6)	/* End of desc table int */
-#define VINO_CTRL_B_INT			(VINO_CTRL_B_EOF_INT | \
-					 VINO_CTRL_B_FIFO_INT | \
-					 VINO_CTRL_B_EOD_INT)
-#define VINO_CTRL_A_DMA_ENBL		(1<<7)
-#define VINO_CTRL_A_INTERLEAVE_ENBL	(1<<8)
-#define VINO_CTRL_A_SYNC_ENBL		(1<<9)
-#define VINO_CTRL_A_SELECT		(1<<10)	/* 1=D1 0=Philips */
-#define VINO_CTRL_A_RGB			(1<<11)	/* 1=RGB 0=YUV */
-#define VINO_CTRL_A_LUMA_ONLY		(1<<12)
-#define VINO_CTRL_A_DEC_ENBL		(1<<13)	/* Decimation */
-#define VINO_CTRL_A_DEC_SCALE_MASK	0x1c000	/* bits 14:17 */
-#define VINO_CTRL_A_DEC_SCALE_SHIFT	(14)
-#define VINO_CTRL_A_DEC_HOR_ONLY	(1<<17)	/* Horizontal only */
-#define VINO_CTRL_A_DITHER		(1<<18)	/* 24 -> 8 bit dither */
-#define VINO_CTRL_B_DMA_ENBL		(1<<19)
-#define VINO_CTRL_B_INTERLEAVE_ENBL	(1<<20)
-#define VINO_CTRL_B_SYNC_ENBL		(1<<21)
-#define VINO_CTRL_B_SELECT		(1<<22)	/* 1=D1 0=Philips */
-#define VINO_CTRL_B_RGB			(1<<23)	/* 1=RGB 0=YUV */
-#define VINO_CTRL_B_LUMA_ONLY		(1<<24)
-#define VINO_CTRL_B_DEC_ENBL		(1<<25)	/* Decimation */
-#define VINO_CTRL_B_DEC_SCALE_MASK	0x1c000000	/* bits 26:28 */
-#define VINO_CTRL_B_DEC_SCALE_SHIFT	(26)
-#define VINO_CTRL_B_DEC_HOR_ONLY	(1<<29)	/* Decimation horizontal only */
-#define VINO_CTRL_B_DITHER		(1<<30)	/* ChanB 24 -> 8 bit dither */
-	u32 _pad_control;
-	volatile u32 control;
-
-#define VINO_INTSTAT_A_EOF		(1<<0)	/* Field transferred int */
-#define VINO_INTSTAT_A_FIFO		(1<<1)	/* FIFO overflow int */
-#define VINO_INTSTAT_A_EOD		(1<<2)	/* End of desc table int */
-#define VINO_INTSTAT_A			(VINO_INTSTAT_A_EOF | \
-					 VINO_INTSTAT_A_FIFO | \
-					 VINO_INTSTAT_A_EOD)
-#define VINO_INTSTAT_B_EOF		(1<<3)	/* Field transferred int */
-#define VINO_INTSTAT_B_FIFO		(1<<4)	/* FIFO overflow int */
-#define VINO_INTSTAT_B_EOD		(1<<5)	/* End of desc table int */
-#define VINO_INTSTAT_B			(VINO_INTSTAT_B_EOF | \
-					 VINO_INTSTAT_B_FIFO | \
-					 VINO_INTSTAT_B_EOD)
-	u32 _pad_intr_status;
-	volatile u32 intr_status;
-
-	u32 _pad_i2c_control;
-	volatile u32 i2c_control;
-	u32 _pad_i2c_data;
-	volatile u32 i2c_data;
-
-	struct sgi_vino_channel a;
-	struct sgi_vino_channel b;
-};
-
-#endif
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 9e758a8f890d..162689227a23 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -27,10 +27,12 @@
 #include <linux/export.h>
 #include <linux/hdmi.h>
 #include <linux/string.h>
+#include <linux/device.h>
 
-static void hdmi_infoframe_checksum(void *buffer, size_t size)
+#define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)
+
+static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
 {
-	u8 *ptr = buffer;
 	u8 csum = 0;
 	size_t i;
 
@@ -38,7 +40,14 @@ static void hdmi_infoframe_checksum(void *buffer, size_t size)
 	for (i = 0; i < size; i++)
 		csum += ptr[i];
 
-	ptr[3] = 256 - csum;
+	return 256 - csum;
+}
+
+static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
+{
+	u8 *ptr = buffer;
+
+	ptr[3] = hdmi_infoframe_checksum(buffer, size);
 }
 
 /**
@@ -136,7 +145,7 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
 	ptr[11] = frame->right_bar & 0xff;
 	ptr[12] = (frame->right_bar >> 8) & 0xff;
 
-	hdmi_infoframe_checksum(buffer, length);
+	hdmi_infoframe_set_checksum(buffer, length);
 
 	return length;
 }
@@ -206,7 +215,7 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
 
 	ptr[24] = frame->sdi;
 
-	hdmi_infoframe_checksum(buffer, length);
+	hdmi_infoframe_set_checksum(buffer, length);
 
 	return length;
 }
@@ -281,7 +290,7 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
 	if (frame->downmix_inhibit)
 		ptr[4] |= BIT(7);
 
-	hdmi_infoframe_checksum(buffer, length);
+	hdmi_infoframe_set_checksum(buffer, length);
 
 	return length;
 }
@@ -373,7 +382,7 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
 			ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
 	}
 
-	hdmi_infoframe_checksum(buffer, length);
+	hdmi_infoframe_set_checksum(buffer, length);
 
 	return length;
 }
@@ -434,3 +443,802 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size)
 	return length;
 }
 EXPORT_SYMBOL(hdmi_infoframe_pack);
+
+static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)
+{
+	if (type < 0x80 || type > 0x9f)
+		return "Invalid";
+	switch (type) {
+	case HDMI_INFOFRAME_TYPE_VENDOR:
+		return "Vendor";
+	case HDMI_INFOFRAME_TYPE_AVI:
+		return "Auxiliary Video Information (AVI)";
+	case HDMI_INFOFRAME_TYPE_SPD:
+		return "Source Product Description (SPD)";
+	case HDMI_INFOFRAME_TYPE_AUDIO:
+		return "Audio";
+	}
+	return "Reserved";
+}
+
+static void hdmi_infoframe_log_header(const char *level,
+				      struct device *dev,
+				      struct hdmi_any_infoframe *frame)
+{
+	hdmi_log("HDMI infoframe: %s, version %u, length %u\n",
+		hdmi_infoframe_type_get_name(frame->type),
+		frame->version, frame->length);
+}
+
+static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)
+{
+	switch (colorspace) {
+	case HDMI_COLORSPACE_RGB:
+		return "RGB";
+	case HDMI_COLORSPACE_YUV422:
+		return "YCbCr 4:2:2";
+	case HDMI_COLORSPACE_YUV444:
+		return "YCbCr 4:4:4";
+	case HDMI_COLORSPACE_YUV420:
+		return "YCbCr 4:2:0";
+	case HDMI_COLORSPACE_RESERVED4:
+		return "Reserved (4)";
+	case HDMI_COLORSPACE_RESERVED5:
+		return "Reserved (5)";
+	case HDMI_COLORSPACE_RESERVED6:
+		return "Reserved (6)";
+	case HDMI_COLORSPACE_IDO_DEFINED:
+		return "IDO Defined";
+	}
+	return "Invalid";
+}
+
+static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)
+{
+	switch (scan_mode) {
+	case HDMI_SCAN_MODE_NONE:
+		return "No Data";
+	case HDMI_SCAN_MODE_OVERSCAN:
+		return "Overscan";
+	case HDMI_SCAN_MODE_UNDERSCAN:
+		return "Underscan";
+	case HDMI_SCAN_MODE_RESERVED:
+		return "Reserved";
+	}
+	return "Invalid";
+}
+
+static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)
+{
+	switch (colorimetry) {
+	case HDMI_COLORIMETRY_NONE:
+		return "No Data";
+	case HDMI_COLORIMETRY_ITU_601:
+		return "ITU601";
+	case HDMI_COLORIMETRY_ITU_709:
+		return "ITU709";
+	case HDMI_COLORIMETRY_EXTENDED:
+		return "Extended";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)
+{
+	switch (picture_aspect) {
+	case HDMI_PICTURE_ASPECT_NONE:
+		return "No Data";
+	case HDMI_PICTURE_ASPECT_4_3:
+		return "4:3";
+	case HDMI_PICTURE_ASPECT_16_9:
+		return "16:9";
+	case HDMI_PICTURE_ASPECT_RESERVED:
+		return "Reserved";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)
+{
+	if (active_aspect < 0 || active_aspect > 0xf)
+		return "Invalid";
+
+	switch (active_aspect) {
+	case HDMI_ACTIVE_ASPECT_16_9_TOP:
+		return "16:9 Top";
+	case HDMI_ACTIVE_ASPECT_14_9_TOP:
+		return "14:9 Top";
+	case HDMI_ACTIVE_ASPECT_16_9_CENTER:
+		return "16:9 Center";
+	case HDMI_ACTIVE_ASPECT_PICTURE:
+		return "Same as Picture";
+	case HDMI_ACTIVE_ASPECT_4_3:
+		return "4:3";
+	case HDMI_ACTIVE_ASPECT_16_9:
+		return "16:9";
+	case HDMI_ACTIVE_ASPECT_14_9:
+		return "14:9";
+	case HDMI_ACTIVE_ASPECT_4_3_SP_14_9:
+		return "4:3 SP 14:9";
+	case HDMI_ACTIVE_ASPECT_16_9_SP_14_9:
+		return "16:9 SP 14:9";
+	case HDMI_ACTIVE_ASPECT_16_9_SP_4_3:
+		return "16:9 SP 4:3";
+	}
+	return "Reserved";
+}
+
+static const char *
+hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)
+{
+	switch (ext_col) {
+	case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
+		return "xvYCC 601";
+	case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
+		return "xvYCC 709";
+	case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
+		return "sYCC 601";
+	case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601:
+		return "Adobe YCC 601";
+	case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB:
+		return "Adobe RGB";
+	case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
+		return "BT.2020 Constant Luminance";
+	case HDMI_EXTENDED_COLORIMETRY_BT2020:
+		return "BT.2020";
+	case HDMI_EXTENDED_COLORIMETRY_RESERVED:
+		return "Reserved";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)
+{
+	switch (qrange) {
+	case HDMI_QUANTIZATION_RANGE_DEFAULT:
+		return "Default";
+	case HDMI_QUANTIZATION_RANGE_LIMITED:
+		return "Limited";
+	case HDMI_QUANTIZATION_RANGE_FULL:
+		return "Full";
+	case HDMI_QUANTIZATION_RANGE_RESERVED:
+		return "Reserved";
+	}
+	return "Invalid";
+}
+
+static const char *hdmi_nups_get_name(enum hdmi_nups nups)
+{
+	switch (nups) {
+	case HDMI_NUPS_UNKNOWN:
+		return "Unknown Non-uniform Scaling";
+	case HDMI_NUPS_HORIZONTAL:
+		return "Horizontally Scaled";
+	case HDMI_NUPS_VERTICAL:
+		return "Vertically Scaled";
+	case HDMI_NUPS_BOTH:
+		return "Horizontally and Vertically Scaled";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)
+{
+	switch (qrange) {
+	case HDMI_YCC_QUANTIZATION_RANGE_LIMITED:
+		return "Limited";
+	case HDMI_YCC_QUANTIZATION_RANGE_FULL:
+		return "Full";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_content_type_get_name(enum hdmi_content_type content_type)
+{
+	switch (content_type) {
+	case HDMI_CONTENT_TYPE_GRAPHICS:
+		return "Graphics";
+	case HDMI_CONTENT_TYPE_PHOTO:
+		return "Photo";
+	case HDMI_CONTENT_TYPE_CINEMA:
+		return "Cinema";
+	case HDMI_CONTENT_TYPE_GAME:
+		return "Game";
+	}
+	return "Invalid";
+}
+
+/**
+ * hdmi_avi_infoframe_log() - log info of HDMI AVI infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI AVI infoframe
+ */
+static void hdmi_avi_infoframe_log(const char *level,
+				   struct device *dev,
+				   struct hdmi_avi_infoframe *frame)
+{
+	hdmi_infoframe_log_header(level, dev,
+				  (struct hdmi_any_infoframe *)frame);
+
+	hdmi_log("    colorspace: %s\n",
+			hdmi_colorspace_get_name(frame->colorspace));
+	hdmi_log("    scan mode: %s\n",
+			hdmi_scan_mode_get_name(frame->scan_mode));
+	hdmi_log("    colorimetry: %s\n",
+			hdmi_colorimetry_get_name(frame->colorimetry));
+	hdmi_log("    picture aspect: %s\n",
+			hdmi_picture_aspect_get_name(frame->picture_aspect));
+	hdmi_log("    active aspect: %s\n",
+			hdmi_active_aspect_get_name(frame->active_aspect));
+	hdmi_log("    itc: %s\n", frame->itc ? "IT Content" : "No Data");
+	hdmi_log("    extended colorimetry: %s\n",
+			hdmi_extended_colorimetry_get_name(frame->extended_colorimetry));
+	hdmi_log("    quantization range: %s\n",
+			hdmi_quantization_range_get_name(frame->quantization_range));
+	hdmi_log("    nups: %s\n", hdmi_nups_get_name(frame->nups));
+	hdmi_log("    video code: %u\n", frame->video_code);
+	hdmi_log("    ycc quantization range: %s\n",
+			hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range));
+	hdmi_log("    hdmi content type: %s\n",
+			hdmi_content_type_get_name(frame->content_type));
+	hdmi_log("    pixel repeat: %u\n", frame->pixel_repeat);
+	hdmi_log("    bar top %u, bottom %u, left %u, right %u\n",
+			frame->top_bar, frame->bottom_bar,
+			frame->left_bar, frame->right_bar);
+}
+
+static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)
+{
+	if (sdi < 0 || sdi > 0xff)
+		return "Invalid";
+	switch (sdi) {
+	case HDMI_SPD_SDI_UNKNOWN:
+		return "Unknown";
+	case HDMI_SPD_SDI_DSTB:
+		return "Digital STB";
+	case HDMI_SPD_SDI_DVDP:
+		return "DVD Player";
+	case HDMI_SPD_SDI_DVHS:
+		return "D-VHS";
+	case HDMI_SPD_SDI_HDDVR:
+		return "HDD Videorecorder";
+	case HDMI_SPD_SDI_DVC:
+		return "DVC";
+	case HDMI_SPD_SDI_DSC:
+		return "DSC";
+	case HDMI_SPD_SDI_VCD:
+		return "Video CD";
+	case HDMI_SPD_SDI_GAME:
+		return "Game";
+	case HDMI_SPD_SDI_PC:
+		return "PC General";
+	case HDMI_SPD_SDI_BD:
+		return "Blu-Ray Disc (BD)";
+	case HDMI_SPD_SDI_SACD:
+		return "Super Audio CD";
+	case HDMI_SPD_SDI_HDDVD:
+		return "HD DVD";
+	case HDMI_SPD_SDI_PMP:
+		return "PMP";
+	}
+	return "Reserved";
+}
+
+/**
+ * hdmi_spd_infoframe_log() - log info of HDMI SPD infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI SPD infoframe
+ */
+static void hdmi_spd_infoframe_log(const char *level,
+				   struct device *dev,
+				   struct hdmi_spd_infoframe *frame)
+{
+	u8 buf[17];
+
+	hdmi_infoframe_log_header(level, dev,
+				  (struct hdmi_any_infoframe *)frame);
+
+	memset(buf, 0, sizeof(buf));
+
+	strncpy(buf, frame->vendor, 8);
+	hdmi_log("    vendor: %s\n", buf);
+	strncpy(buf, frame->product, 16);
+	hdmi_log("    product: %s\n", buf);
+	hdmi_log("    source device information: %s (0x%x)\n",
+		hdmi_spd_sdi_get_name(frame->sdi), frame->sdi);
+}
+
+static const char *
+hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)
+{
+	switch (coding_type) {
+	case HDMI_AUDIO_CODING_TYPE_STREAM:
+		return "Refer to Stream Header";
+	case HDMI_AUDIO_CODING_TYPE_PCM:
+		return "PCM";
+	case HDMI_AUDIO_CODING_TYPE_AC3:
+		return "AC-3";
+	case HDMI_AUDIO_CODING_TYPE_MPEG1:
+		return "MPEG1";
+	case HDMI_AUDIO_CODING_TYPE_MP3:
+		return "MP3";
+	case HDMI_AUDIO_CODING_TYPE_MPEG2:
+		return "MPEG2";
+	case HDMI_AUDIO_CODING_TYPE_AAC_LC:
+		return "AAC";
+	case HDMI_AUDIO_CODING_TYPE_DTS:
+		return "DTS";
+	case HDMI_AUDIO_CODING_TYPE_ATRAC:
+		return "ATRAC";
+	case HDMI_AUDIO_CODING_TYPE_DSD:
+		return "One Bit Audio";
+	case HDMI_AUDIO_CODING_TYPE_EAC3:
+		return "Dolby Digital +";
+	case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+		return "DTS-HD";
+	case HDMI_AUDIO_CODING_TYPE_MLP:
+		return "MAT (MLP)";
+	case HDMI_AUDIO_CODING_TYPE_DST:
+		return "DST";
+	case HDMI_AUDIO_CODING_TYPE_WMA_PRO:
+		return "WMA PRO";
+	case HDMI_AUDIO_CODING_TYPE_CXT:
+		return "Refer to CXT";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)
+{
+	switch (sample_size) {
+	case HDMI_AUDIO_SAMPLE_SIZE_STREAM:
+		return "Refer to Stream Header";
+	case HDMI_AUDIO_SAMPLE_SIZE_16:
+		return "16 bit";
+	case HDMI_AUDIO_SAMPLE_SIZE_20:
+		return "20 bit";
+	case HDMI_AUDIO_SAMPLE_SIZE_24:
+		return "24 bit";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)
+{
+	switch (freq) {
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM:
+		return "Refer to Stream Header";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_32000:
+		return "32 kHz";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_44100:
+		return "44.1 kHz (CD)";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_48000:
+		return "48 kHz";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_88200:
+		return "88.2 kHz";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_96000:
+		return "96 kHz";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_176400:
+		return "176.4 kHz";
+	case HDMI_AUDIO_SAMPLE_FREQUENCY_192000:
+		return "192 kHz";
+	}
+	return "Invalid";
+}
+
+static const char *
+hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)
+{
+	if (ctx < 0 || ctx > 0x1f)
+		return "Invalid";
+
+	switch (ctx) {
+	case HDMI_AUDIO_CODING_TYPE_EXT_CT:
+		return "Refer to CT";
+	case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC:
+		return "HE AAC";
+	case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2:
+		return "HE AAC v2";
+	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND:
+		return "MPEG SURROUND";
+	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC:
+		return "MPEG-4 HE AAC";
+	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2:
+		return "MPEG-4 HE AAC v2";
+	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC:
+		return "MPEG-4 AAC LC";
+	case HDMI_AUDIO_CODING_TYPE_EXT_DRA:
+		return "DRA";
+	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND:
+		return "MPEG-4 HE AAC + MPEG Surround";
+	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND:
+		return "MPEG-4 AAC LC + MPEG Surround";
+	}
+	return "Reserved";
+}
+
+/**
+ * hdmi_audio_infoframe_log() - log info of HDMI AUDIO infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI AUDIO infoframe
+ */
+static void hdmi_audio_infoframe_log(const char *level,
+				     struct device *dev,
+				     struct hdmi_audio_infoframe *frame)
+{
+	hdmi_infoframe_log_header(level, dev,
+				  (struct hdmi_any_infoframe *)frame);
+
+	if (frame->channels)
+		hdmi_log("    channels: %u\n", frame->channels - 1);
+	else
+		hdmi_log("    channels: Refer to stream header\n");
+	hdmi_log("    coding type: %s\n",
+			hdmi_audio_coding_type_get_name(frame->coding_type));
+	hdmi_log("    sample size: %s\n",
+			hdmi_audio_sample_size_get_name(frame->sample_size));
+	hdmi_log("    sample frequency: %s\n",
+			hdmi_audio_sample_frequency_get_name(frame->sample_frequency));
+	hdmi_log("    coding type ext: %s\n",
+			hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext));
+	hdmi_log("    channel allocation: 0x%x\n",
+			frame->channel_allocation);
+	hdmi_log("    level shift value: %u dB\n",
+			frame->level_shift_value);
+	hdmi_log("    downmix inhibit: %s\n",
+			frame->downmix_inhibit ? "Yes" : "No");
+}
+
+static const char *
+hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)
+{
+	if (s3d_struct < 0 || s3d_struct > 0xf)
+		return "Invalid";
+
+	switch (s3d_struct) {
+	case HDMI_3D_STRUCTURE_FRAME_PACKING:
+		return "Frame Packing";
+	case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE:
+		return "Field Alternative";
+	case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE:
+		return "Line Alternative";
+	case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL:
+		return "Side-by-side (Full)";
+	case HDMI_3D_STRUCTURE_L_DEPTH:
+		return "L + Depth";
+	case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH:
+		return "L + Depth + Graphics + Graphics-depth";
+	case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM:
+		return "Top-and-Bottom";
+	case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF:
+		return "Side-by-side (Half)";
+	default:
+		break;
+	}
+	return "Reserved";
+}
+
+/**
+ * hdmi_vendor_infoframe_log() - log info of HDMI VENDOR infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI VENDOR infoframe
+ */
+static void
+hdmi_vendor_any_infoframe_log(const char *level,
+			      struct device *dev,
+			      union hdmi_vendor_any_infoframe *frame)
+{
+	struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
+
+	hdmi_infoframe_log_header(level, dev,
+				  (struct hdmi_any_infoframe *)frame);
+
+	if (frame->any.oui != HDMI_IEEE_OUI) {
+		hdmi_log("    not a HDMI vendor infoframe\n");
+		return;
+	}
+	if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) {
+		hdmi_log("    empty frame\n");
+		return;
+	}
+
+	if (hvf->vic)
+		hdmi_log("    HDMI VIC: %u\n", hvf->vic);
+	if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
+		hdmi_log("    3D structure: %s\n",
+				hdmi_3d_structure_get_name(hvf->s3d_struct));
+		if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
+			hdmi_log("    3D extension data: %d\n",
+					hvf->s3d_ext_data);
+	}
+}
+
+/**
+ * hdmi_infoframe_log() - log info of HDMI infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI infoframe
+ */
+void hdmi_infoframe_log(const char *level,
+			struct device *dev,
+			union hdmi_infoframe *frame)
+{
+	switch (frame->any.type) {
+	case HDMI_INFOFRAME_TYPE_AVI:
+		hdmi_avi_infoframe_log(level, dev, &frame->avi);
+		break;
+	case HDMI_INFOFRAME_TYPE_SPD:
+		hdmi_spd_infoframe_log(level, dev, &frame->spd);
+		break;
+	case HDMI_INFOFRAME_TYPE_AUDIO:
+		hdmi_audio_infoframe_log(level, dev, &frame->audio);
+		break;
+	case HDMI_INFOFRAME_TYPE_VENDOR:
+		hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);
+		break;
+	}
+}
+EXPORT_SYMBOL(hdmi_infoframe_log);
+
+/**
+ * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe
+ * @buffer: source buffer
+ * @frame: HDMI AVI infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Auxiliary Video (AVI) information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
+				     void *buffer)
+{
+	u8 *ptr = buffer;
+	int ret;
+
+	if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
+	    ptr[1] != 2 ||
+	    ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
+		return -EINVAL;
+
+	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
+		return -EINVAL;
+
+	ret = hdmi_avi_infoframe_init(frame);
+	if (ret)
+		return ret;
+
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	frame->colorspace = (ptr[0] >> 5) & 0x3;
+	if (ptr[0] & 0x10)
+		frame->active_aspect = ptr[1] & 0xf;
+	if (ptr[0] & 0x8) {
+		frame->top_bar = (ptr[5] << 8) + ptr[6];
+		frame->bottom_bar = (ptr[7] << 8) + ptr[8];
+	}
+	if (ptr[0] & 0x4) {
+		frame->left_bar = (ptr[9] << 8) + ptr[10];
+		frame->right_bar = (ptr[11] << 8) + ptr[12];
+	}
+	frame->scan_mode = ptr[0] & 0x3;
+
+	frame->colorimetry = (ptr[1] >> 6) & 0x3;
+	frame->picture_aspect = (ptr[1] >> 4) & 0x3;
+	frame->active_aspect = ptr[1] & 0xf;
+
+	frame->itc = ptr[2] & 0x80 ? true : false;
+	frame->extended_colorimetry = (ptr[2] >> 4) & 0x7;
+	frame->quantization_range = (ptr[2] >> 2) & 0x3;
+	frame->nups = ptr[2] & 0x3;
+
+	frame->video_code = ptr[3] & 0x7f;
+	frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3;
+	frame->content_type = (ptr[4] >> 4) & 0x3;
+
+	frame->pixel_repeat = ptr[4] & 0xf;
+
+	return 0;
+}
+
+/**
+ * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe
+ * @buffer: source buffer
+ * @frame: HDMI SPD infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Source Product Description (SPD) information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
+				     void *buffer)
+{
+	u8 *ptr = buffer;
+	int ret;
+
+	if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
+	    ptr[1] != 1 ||
+	    ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
+		return -EINVAL;
+	}
+
+	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0)
+		return -EINVAL;
+
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8);
+	if (ret)
+		return ret;
+
+	frame->sdi = ptr[24];
+
+	return 0;
+}
+
+/**
+ * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe
+ * @buffer: source buffer
+ * @frame: HDMI Audio infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Audio information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
+				       void *buffer)
+{
+	u8 *ptr = buffer;
+	int ret;
+
+	if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
+	    ptr[1] != 1 ||
+	    ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
+		return -EINVAL;
+	}
+
+	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0)
+		return -EINVAL;
+
+	ret = hdmi_audio_infoframe_init(frame);
+	if (ret)
+		return ret;
+
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	frame->channels = ptr[0] & 0x7;
+	frame->coding_type = (ptr[0] >> 4) & 0xf;
+	frame->sample_size = ptr[1] & 0x3;
+	frame->sample_frequency = (ptr[1] >> 2) & 0x7;
+	frame->coding_type_ext = ptr[2] & 0x1f;
+	frame->channel_allocation = ptr[3];
+	frame->level_shift_value = (ptr[4] >> 3) & 0xf;
+	frame->downmix_inhibit = ptr[4] & 0x80 ? true : false;
+
+	return 0;
+}
+
+/**
+ * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe
+ * @buffer: source buffer
+ * @frame: HDMI Vendor infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Vendor information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
+				 void *buffer)
+{
+	u8 *ptr = buffer;
+	size_t length;
+	int ret;
+	u8 hdmi_video_format;
+	struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
+
+	if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
+	    ptr[1] != 1 ||
+	    (ptr[2] != 5 && ptr[2] != 6))
+		return -EINVAL;
+
+	length = ptr[2];
+
+	if (hdmi_infoframe_checksum(buffer,
+				    HDMI_INFOFRAME_HEADER_SIZE + length) != 0)
+		return -EINVAL;
+
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	/* HDMI OUI */
+	if ((ptr[0] != 0x03) ||
+	    (ptr[1] != 0x0c) ||
+	    (ptr[2] != 0x00))
+		return -EINVAL;
+
+	hdmi_video_format = ptr[3] >> 5;
+
+	if (hdmi_video_format > 0x2)
+		return -EINVAL;
+
+	ret = hdmi_vendor_infoframe_init(hvf);
+	if (ret)
+		return ret;
+
+	hvf->length = length;
+
+	if (hdmi_video_format == 0x1) {
+		hvf->vic = ptr[4];
+	} else if (hdmi_video_format == 0x2) {
+		hvf->s3d_struct = ptr[4] >> 4;
+		if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {
+			if (length == 6)
+				hvf->s3d_ext_data = ptr[5] >> 4;
+			else
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
+ * @buffer: source buffer
+ * @frame: HDMI infoframe
+ *
+ * Unpacks the information contained in binary buffer @buffer into a structured
+ * @frame of a HDMI infoframe.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer)
+{
+	int ret;
+	u8 *ptr = buffer;
+
+	switch (ptr[0]) {
+	case HDMI_INFOFRAME_TYPE_AVI:
+		ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer);
+		break;
+	case HDMI_INFOFRAME_TYPE_SPD:
+		ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer);
+		break;
+	case HDMI_INFOFRAME_TYPE_AUDIO:
+		ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer);
+		break;
+	case HDMI_INFOFRAME_TYPE_VENDOR:
+		ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(hdmi_infoframe_unpack);
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index cbb5790a35cd..e9744202fa29 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -25,6 +25,7 @@
 #define __LINUX_HDMI_H_
 
 #include <linux/types.h>
+#include <linux/device.h>
 
 enum hdmi_infoframe_type {
 	HDMI_INFOFRAME_TYPE_VENDOR = 0x81,
@@ -52,12 +53,18 @@ enum hdmi_colorspace {
 	HDMI_COLORSPACE_RGB,
 	HDMI_COLORSPACE_YUV422,
 	HDMI_COLORSPACE_YUV444,
+	HDMI_COLORSPACE_YUV420,
+	HDMI_COLORSPACE_RESERVED4,
+	HDMI_COLORSPACE_RESERVED5,
+	HDMI_COLORSPACE_RESERVED6,
+	HDMI_COLORSPACE_IDO_DEFINED,
 };
 
 enum hdmi_scan_mode {
 	HDMI_SCAN_MODE_NONE,
 	HDMI_SCAN_MODE_OVERSCAN,
 	HDMI_SCAN_MODE_UNDERSCAN,
+	HDMI_SCAN_MODE_RESERVED,
 };
 
 enum hdmi_colorimetry {
@@ -71,6 +78,7 @@ enum hdmi_picture_aspect {
 	HDMI_PICTURE_ASPECT_NONE,
 	HDMI_PICTURE_ASPECT_4_3,
 	HDMI_PICTURE_ASPECT_16_9,
+	HDMI_PICTURE_ASPECT_RESERVED,
 };
 
 enum hdmi_active_aspect {
@@ -92,12 +100,18 @@ enum hdmi_extended_colorimetry {
 	HDMI_EXTENDED_COLORIMETRY_S_YCC_601,
 	HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601,
 	HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB,
+
+	/* The following EC values are only defined in CEA-861-F. */
+	HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM,
+	HDMI_EXTENDED_COLORIMETRY_BT2020,
+	HDMI_EXTENDED_COLORIMETRY_RESERVED,
 };
 
 enum hdmi_quantization_range {
 	HDMI_QUANTIZATION_RANGE_DEFAULT,
 	HDMI_QUANTIZATION_RANGE_LIMITED,
 	HDMI_QUANTIZATION_RANGE_FULL,
+	HDMI_QUANTIZATION_RANGE_RESERVED,
 };
 
 /* non-uniform picture scaling */
@@ -114,7 +128,7 @@ enum hdmi_ycc_quantization_range {
 };
 
 enum hdmi_content_type {
-	HDMI_CONTENT_TYPE_NONE,
+	HDMI_CONTENT_TYPE_GRAPHICS,
 	HDMI_CONTENT_TYPE_PHOTO,
 	HDMI_CONTENT_TYPE_CINEMA,
 	HDMI_CONTENT_TYPE_GAME,
@@ -194,6 +208,7 @@ enum hdmi_audio_coding_type {
 	HDMI_AUDIO_CODING_TYPE_MLP,
 	HDMI_AUDIO_CODING_TYPE_DST,
 	HDMI_AUDIO_CODING_TYPE_WMA_PRO,
+	HDMI_AUDIO_CODING_TYPE_CXT,
 };
 
 enum hdmi_audio_sample_size {
@@ -215,10 +230,25 @@ enum hdmi_audio_sample_frequency {
 };
 
 enum hdmi_audio_coding_type_ext {
-	HDMI_AUDIO_CODING_TYPE_EXT_STREAM,
+	/* Refer to Audio Coding Type (CT) field in Data Byte 1 */
+	HDMI_AUDIO_CODING_TYPE_EXT_CT,
+
+	/*
+	 * The next three CXT values are defined in CEA-861-E only.
+	 * They do not exist in older versions, and in CEA-861-F they are
+	 * defined as 'Not in use'.
+	 */
 	HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC,
 	HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2,
 	HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND,
+
+	/* The following CXT values are only defined in CEA-861-F. */
+	HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC,
+	HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2,
+	HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC,
+	HDMI_AUDIO_CODING_TYPE_EXT_DRA,
+	HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND,
+	HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND = 10,
 };
 
 struct hdmi_audio_infoframe {
@@ -299,5 +329,8 @@ union hdmi_infoframe {
 
 ssize_t
 hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size);
+int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer);
+void hdmi_infoframe_log(const char *level, struct device *dev,
+			union hdmi_infoframe *frame);
 
 #endif /* _DRM_HDMI_H */
diff --git a/include/linux/platform_data/vsp1.h b/include/linux/platform_data/vsp1.h
deleted file mode 100644
index 63170e2614b3..000000000000
--- a/include/linux/platform_data/vsp1.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * vsp1.h  --  R-Car VSP1 Platform Data
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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 __PLATFORM_VSP1_H__
-#define __PLATFORM_VSP1_H__
-
-#define VSP1_HAS_LIF		(1 << 0)
-#define VSP1_HAS_LUT		(1 << 1)
-#define VSP1_HAS_SRU		(1 << 2)
-
-struct vsp1_platform_data {
-	unsigned int features;
-	unsigned int rpf_count;
-	unsigned int uds_count;
-	unsigned int wpf_count;
-};
-
-#endif /* __PLATFORM_VSP1_H__ */
diff --git a/include/media/smiapp.h b/include/media/smiapp.h
index 0b8f124a630c..268a3cdbf6cb 100644
--- a/include/media/smiapp.h
+++ b/include/media/smiapp.h
@@ -65,19 +65,19 @@ struct smiapp_platform_data {
 	unsigned short i2c_addr_dfl;	/* Default i2c addr */
 	unsigned short i2c_addr_alt;	/* Alternate i2c addr */
 
-	unsigned int nvm_size;			/* bytes */
-	unsigned int ext_clk;			/* sensor external clk */
+	uint32_t nvm_size;		/* bytes */
+	uint32_t ext_clk;		/* sensor external clk */
 
 	unsigned int lanes;		/* Number of CSI-2 lanes */
-	u8 csi_signalling_mode;		/* SMIAPP_CSI_SIGNALLING_MODE_* */
-	const s64 *op_sys_clock;
+	uint32_t csi_signalling_mode;	/* SMIAPP_CSI_SIGNALLING_MODE_* */
+	uint64_t *op_sys_clock;
 
 	enum smiapp_module_board_orient module_board_orient;
 
 	struct smiapp_flash_strobe_parms *strobe_setup;
 
 	int (*set_xclk)(struct v4l2_subdev *sd, int hz);
-	int xshutdown;			/* gpio or SMIAPP_NO_XSHUTDOWN */
+	int32_t xshutdown;		/* gpio or SMIAPP_NO_XSHUTDOWN */
 };
 
 #endif /* __SMIAPP_H_  */
diff --git a/include/media/tea575x.h b/include/media/tea575x.h
index 2d4fa59db902..5d096578b736 100644
--- a/include/media/tea575x.h
+++ b/include/media/tea575x.h
@@ -71,6 +71,11 @@ struct snd_tea575x {
 	int (*ext_init)(struct snd_tea575x *tea);
 };
 
+int snd_tea575x_enum_freq_bands(struct snd_tea575x *tea,
+					struct v4l2_frequency_band *band);
+int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v);
+int snd_tea575x_s_hw_freq_seek(struct file *file, struct snd_tea575x *tea,
+				const struct v4l2_hw_freq_seek *a);
 int snd_tea575x_hw_init(struct snd_tea575x *tea);
 int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner);
 void snd_tea575x_exit(struct snd_tea575x *tea);
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index eb76cfd47189..3e4fddfc840c 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -124,7 +124,8 @@ struct video_device
 	spinlock_t		fh_lock; /* Lock for all v4l2_fhs */
 	struct list_head	fh_list; /* List of struct v4l2_fh */
 
-	int debug;			/* Activates debug level*/
+	/* Internal device debug flags, not for use by drivers */
+	int dev_debug;
 
 	/* Video standard vars */
 	v4l2_std_id tvnorms;		/* Supported tv norms */
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 53605f0f9903..8537983b9b22 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -291,9 +291,18 @@ struct v4l2_ioctl_ops {
 
 /* v4l debugging and diagnostics */
 
-/* Debug bitmask flags to be used on V4L2 */
-#define V4L2_DEBUG_IOCTL     0x01
-#define V4L2_DEBUG_IOCTL_ARG 0x02
+/* Device debug flags to be used with the video device debug attribute */
+
+/* Just log the ioctl name + error code */
+#define V4L2_DEV_DEBUG_IOCTL		0x01
+/* Log the ioctl name arguments + error code */
+#define V4L2_DEV_DEBUG_IOCTL_ARG	0x02
+/* Log the file operations open, release, mmap and get_unmapped_area */
+#define V4L2_DEV_DEBUG_FOP		0x04
+/* Log the read and write file operations and the VIDIOC_(D)QBUF ioctls */
+#define V4L2_DEV_DEBUG_STREAMING	0x08
+/* Log poll() */
+#define V4L2_DEV_DEBUG_POLL		0x10
 
 /*  Video standard functions  */
 extern const char *v4l2_norm_to_name(v4l2_std_id id);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 5860292d42eb..5beeb8744fd1 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -342,8 +342,6 @@ struct v4l2_subdev_video_ops {
 			struct v4l2_dv_timings *timings);
 	int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
 			     u32 *code);
-	int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
-			     struct v4l2_frmsizeenum *fsize);
 	int (*g_mbus_fmt)(struct v4l2_subdev *sd,
 			  struct v4l2_mbus_framefmt *fmt);
 	int (*try_mbus_fmt)(struct v4l2_subdev *sd,
@@ -503,10 +501,6 @@ struct v4l2_subdev_pad_ops {
 		       struct v4l2_subdev_format *format);
 	int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 		       struct v4l2_subdev_format *format);
-	int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-		       struct v4l2_subdev_crop *crop);
-	int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-		       struct v4l2_subdev_crop *crop);
 	int (*get_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 			     struct v4l2_subdev_selection *sel);
 	int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
index fb6fd4d8f4ed..d8b27854e3bf 100644
--- a/include/media/videobuf-dma-sg.h
+++ b/include/media/videobuf-dma-sg.h
@@ -84,16 +84,8 @@ struct videobuf_dma_sg_memory {
  * Despite the name, this is totally unrelated to videobuf, except that
  * videobuf-dma-sg uses the same API internally.
  */
-void videobuf_dma_init(struct videobuf_dmabuf *dma);
-int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
-			   unsigned long data, unsigned long size);
-int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
-			     int nr_pages);
-int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
-			      dma_addr_t addr, int nr_pages);
 int videobuf_dma_free(struct videobuf_dmabuf *dma);
 
-int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma);
 int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma);
 struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf);
 
diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h
index d63965a1faaf..c3bfa473c3aa 100644
--- a/include/media/videobuf-dvb.h
+++ b/include/media/videobuf-dvb.h
@@ -56,9 +56,3 @@ struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_fro
 int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p);
 
 #endif			/* _VIDEOBUF_DVB_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 14b7b6e44c77..7b8141bf59a7 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -35,6 +35,7 @@ header-y += adfs_fs.h
 header-y += affs_hardblocks.h
 header-y += agpgart.h
 header-y += aio_abi.h
+header-y += am437x-vpfe.h
 header-y += apm_bios.h
 header-y += arcfb.h
 header-y += atalk.h
diff --git a/include/uapi/linux/am437x-vpfe.h b/include/uapi/linux/am437x-vpfe.h
new file mode 100644
index 000000000000..9b03033f9cd6
--- /dev/null
+++ b/include/uapi/linux/am437x-vpfe.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013 - 2014 Texas Instruments, Inc.
+ *
+ * Benoit Parrot <bparrot@ti.com>
+ * Lad, Prabhakar <prabhakar.csengg@gmail.com>
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef AM437X_VPFE_USER_H
+#define AM437X_VPFE_USER_H
+
+enum vpfe_ccdc_data_size {
+	VPFE_CCDC_DATA_16BITS = 0,
+	VPFE_CCDC_DATA_15BITS,
+	VPFE_CCDC_DATA_14BITS,
+	VPFE_CCDC_DATA_13BITS,
+	VPFE_CCDC_DATA_12BITS,
+	VPFE_CCDC_DATA_11BITS,
+	VPFE_CCDC_DATA_10BITS,
+	VPFE_CCDC_DATA_8BITS,
+};
+
+/* enum for No of pixel per line to be avg. in Black Clamping*/
+enum vpfe_ccdc_sample_length {
+	VPFE_CCDC_SAMPLE_1PIXELS = 0,
+	VPFE_CCDC_SAMPLE_2PIXELS,
+	VPFE_CCDC_SAMPLE_4PIXELS,
+	VPFE_CCDC_SAMPLE_8PIXELS,
+	VPFE_CCDC_SAMPLE_16PIXELS,
+};
+
+/* enum for No of lines in Black Clamping */
+enum vpfe_ccdc_sample_line {
+	VPFE_CCDC_SAMPLE_1LINES = 0,
+	VPFE_CCDC_SAMPLE_2LINES,
+	VPFE_CCDC_SAMPLE_4LINES,
+	VPFE_CCDC_SAMPLE_8LINES,
+	VPFE_CCDC_SAMPLE_16LINES,
+};
+
+/* enum for Alaw gamma width */
+enum vpfe_ccdc_gamma_width {
+	VPFE_CCDC_GAMMA_BITS_15_6 = 0,	/* use bits 15-6 for gamma */
+	VPFE_CCDC_GAMMA_BITS_14_5,
+	VPFE_CCDC_GAMMA_BITS_13_4,
+	VPFE_CCDC_GAMMA_BITS_12_3,
+	VPFE_CCDC_GAMMA_BITS_11_2,
+	VPFE_CCDC_GAMMA_BITS_10_1,
+	VPFE_CCDC_GAMMA_BITS_09_0,	/* use bits 9-0 for gamma */
+};
+
+/* structure for ALaw */
+struct vpfe_ccdc_a_law {
+	/* Enable/disable A-Law */
+	unsigned char enable;
+	/* Gamma Width Input */
+	enum vpfe_ccdc_gamma_width gamma_wd;
+};
+
+/* structure for Black Clamping */
+struct vpfe_ccdc_black_clamp {
+	unsigned char enable;
+	/* only if bClampEnable is TRUE */
+	enum vpfe_ccdc_sample_length sample_pixel;
+	/* only if bClampEnable is TRUE */
+	enum vpfe_ccdc_sample_line sample_ln;
+	/* only if bClampEnable is TRUE */
+	unsigned short start_pixel;
+	/* only if bClampEnable is TRUE */
+	unsigned short sgain;
+	/* only if bClampEnable is FALSE */
+	unsigned short dc_sub;
+};
+
+/* structure for Black Level Compensation */
+struct vpfe_ccdc_black_compensation {
+	/* Constant value to subtract from Red component */
+	char r;
+	/* Constant value to subtract from Gr component */
+	char gr;
+	/* Constant value to subtract from Blue component */
+	char b;
+	/* Constant value to subtract from Gb component */
+	char gb;
+};
+
+/* Structure for CCDC configuration parameters for raw capture mode passed
+ * by application
+ */
+struct vpfe_ccdc_config_params_raw {
+	/* data size value from 8 to 16 bits */
+	enum vpfe_ccdc_data_size data_sz;
+	/* Structure for Optional A-Law */
+	struct vpfe_ccdc_a_law alaw;
+	/* Structure for Optical Black Clamp */
+	struct vpfe_ccdc_black_clamp blk_clamp;
+	/* Structure for Black Compensation */
+	struct vpfe_ccdc_black_compensation blk_comp;
+};
+
+/*
+ *  Private IOCTL
+ * VIDIOC_AM437X_CCDC_CFG - Set CCDC configuration for raw capture
+ * This is an experimental ioctl that will change in future kernels. So use
+ * this ioctl with care !
+ **/
+#define VIDIOC_AM437X_CCDC_CFG \
+	_IOW('V', BASE_VIDIOC_PRIVATE + 1, void *)
+
+#endif		/* AM437X_VPFE_USER_H */
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 661f119a51b8..9f6e108ff4a0 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -170,6 +170,10 @@ enum v4l2_colorfx {
  * We reserve 16 controls for this driver. */
 #define V4L2_CID_USER_SAA7134_BASE		(V4L2_CID_USER_BASE + 0x1060)
 
+/* The base for the adv7180 driver controls.
+ * We reserve 16 controls for this driver. */
+#define V4L2_CID_USER_ADV7180_BASE		(V4L2_CID_USER_BASE + 0x1070)
+
 /* MPEG-class control IDs */
 /* The MPEG controls are applicable to all codec controls
  * and the 'MPEG' part of the define is historical */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index d279c1b75cf7..fbdc3602ee27 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -463,10 +463,11 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
 #define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
 #define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
-#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12  BGBG.. GRGR.. */
-#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12  GBGB.. RGRG.. */
-#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12  GRGR.. BGBG.. */
-#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12  RGRG.. GBGB.. */
+	/* 10bit raw bayer packed, 5 bytes for every 4 pixels */
+#define V4L2_PIX_FMT_SBGGR10P v4l2_fourcc('p', 'B', 'A', 'A')
+#define V4L2_PIX_FMT_SGBRG10P v4l2_fourcc('p', 'G', 'A', 'A')
+#define V4L2_PIX_FMT_SGRBG10P v4l2_fourcc('p', 'g', 'A', 'A')
+#define V4L2_PIX_FMT_SRGGB10P v4l2_fourcc('p', 'R', 'A', 'A')
 	/* 10bit raw bayer a-law compressed to 8 bits */
 #define V4L2_PIX_FMT_SBGGR10ALAW8 v4l2_fourcc('a', 'B', 'A', '8')
 #define V4L2_PIX_FMT_SGBRG10ALAW8 v4l2_fourcc('a', 'G', 'A', '8')
@@ -477,10 +478,10 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8')
 #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0')
 #define V4L2_PIX_FMT_SRGGB10DPCM8 v4l2_fourcc('b', 'R', 'A', '8')
-	/*
-	 * 10bit raw bayer, expanded to 16 bits
-	 * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
-	 */
+#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12  GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12  RGRG.. GBGB.. */
 #define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16  BGBG.. GRGR.. */
 
 /* compressed formats */